Variable and constants

I’ve taken over a php based site and trying to understand a bit. What I don’t get is the below in the index.php on my site. I’ve included just part of this. The top declares a variable to my understanding. But the use of DOCUMENT_ROOT below and also elsewhere causes PHP to assume a constant. I’m not sure it should be a constant as it looks to me like it’s declared as a variable. I can solve the messages by putting single quotes around DOCUMENT_ROOT I assume telling PHP (5.4) that it’s a constant. But then why declare it as a variable? If I change this in any way it breaks. If I define this is a constant and remove the variable declaration PHP doesn’t end up getting the path right for the include scripts it looks like. Having a tough time understanding. Most other scripts there are no variables declared. Just things like DOCUMENT_ROOT used and other what I assume are constants that can be solved by putting them in single quotes. Also have complaints about variables as they aren’t declared.

<?php $DOCUMENT_ROOT = "/home/mysite/domains/mysite/public_html"; include($_SERVER[DOCUMENT_ROOT] . "/inc/functions.php"); ?>


Notice: Use of undefined constant DOCUMENT_ROOT - assumed ‘DOCUMENT_ROOT’ in […][…] on line 5

The is the result of a collection of bad decisions on php’s part.

The main confusion is due to php allowing an array’s associative index name, that is a string, and should be surrounded by quotes (single or double), to be left un-quoted, which is syntactically how a defined constant would be used in code. Php than assumed that if there is no matching defined constant, that the value should be treated as a string. The error message about this conversion/assumption was always being produced, however php also actively promoted hiding some error types to make code look better than it actually is. Fortunately, the bad decision to do this conversion/assumption is now deprecated and will be removed in the future. The correct syntax for the $_SERVER … variable, which can also be found in the php.net documentation, is -

$_SERVER['DOCUMENT_ROOT']

‘DOCUMENT_ROOT’ in the above is an associative array index name and it is properly a string.

The second bad decision affecting what you have found in the code, is left over from register_globals (removed in php5.4.) With register_globals, the existence of the $_SERVER['DOCUMENT_ROOT'] super-global variable ‘automatically’ caused the regular program variable $DOCUMENT_ROOT to be created and set to whatever value $_SERVER['DOCUMENT_ROOT'] contains. When register_globals were removed, to make the code work again, someone probably manually created the line of code assigning a value to $DOCUMENT_ROOT.

1 Like

This code was on a site that was 10+ years old. I’m running on 5.4 as that’s what’s currently in CentOS 7. In the future I would like to make a project on upgrading.

Thank you for the explanation. I’m admittedly very very beginner and mainly have the admin mindset but I can sorta understand reading things and have doneso to get the site going again.

Your explanation explains how even when I defined the constant it broke things. I’m not a developer so I don’t quite understand. Basically DOCUMENT_ROOT is really a string and not a constant?

Therefore it seems if I want to get rid of all these complaints about constants I need to add the single quote via a find and replace in all the .php files. Am I correct that without doing so the code won’t work if i ever convert to PHP 7?

$_SERVER['DOCUMENT_ROOT'] is a an element of the $_SERVER super-global array variable with the associative index name ‘DOCUMENT_ROOT’. In this case, it is a string, the index name. This variable gets populated based on your web server’s configuration settings. This is the proper syntax.

$_SERVER[DOCUMENT_ROOT] is a badly formed version of the above that produces the offending undefined constant DOCUMENT_ROOT assumed ‘DOCUMENT_ROOT’ error, which will stop working all together at some point in the future.

$DOCUMENT_ROOT is a regular program variable. In this case, it is the name of a php variable.

DOCUMENT_ROOT is the syntax for a defined constant. It would require a define('DOCUMENT_ROOT', 'some value'); statement for it to exist.

The index part you mentioned explains why when I tried to solve it I got complaints when I tried to fix it previously.

PHP Notice: Undefined index: /home/mysite/domains/mysite/public_html in /home/mysite/domains/mysite/public_html/index.php on line 5

I’ll put single quotes around all the elements to get rid of these messages.

Next will be the variables that aren’t defined. I know I have set my variables at the top to solve. Seems to work for most of them. But for this one even if I do $topspace = null; at the beginning of my script I get this. I

PHP Notice: Undefined variable: topspace in /home/mysite/domains/mysite/public_html/inc/page_template.php on line 33

	## Section header template
function lnav_section ($text, $top) {
	if ($top == 1) {
		$topspace = " margin-top: 5px;";
	}
	echo "<div style='background-color: #0168B3; padding: 2px 3px 2px 5px; color: #ffffff; font-size: 13px; font-weight: bold; margin-bottom: 5px;$topspace'><img src='/images/arrow-section.gif' width='12' height='11' border='0' alt='' style='margin-right: 4px' />$text</div>";
}

Functions have their own scope. It means that in each function there are no existing global variables. The reason for this isolation is called code separation. A function must be usable from different scripts (with the help of an include) without the risk that you would accidentally overwrite variable values.

This said you can solve your problem on a few possible manners:

  • pass your value into the function using a third paramater e.g. function nav_section ($text, $top, $topspace)
  • initialize your variable within the function instead of outside the function
function lnav_section ($text, $top) 
{
	$topspace = '';

	if ($top == 1) {
		$topspace = " margin-top: 5px;";
	}
}
  • use the keyword global to make the global variable available inside your function. (This manner is not recommended)
  • Use the superglobal array $GLOBALS to get access to your global variable (also not recommended).

Some additional information about functions

  • There are some superglobal variables in php that also exist in functions.
  • You should not use echo’s in your function. Instead you should echo the result of a function like this:
function lnav_section ($text, $top) 
{
	$topspace = '';

	if ($top == 1) {
		$topspace = " margin-top: 5px;";
	}

	return "<div style='background-color: #0168B3; padding: 2px 3px 2px 5px; color: #ffffff; font-size: 13px; font-weight: bold; margin-bottom: 5px;$topspace'><img src='/images/arrow-section.gif' width='12' height='11' border='0' alt='' style='margin-right: 4px' />$text</div>";
}

echo lnav_section ('example text', true);

Other valuable information:

Thanks I understand. The function doesn’t see the global variable. How do tell whether you should declare the variable globally or in the function? If 2 functions use the same variable you end up having to declare it twice for example? Is it basically functions can’t see global variables?

The logic in that function is setting $topspace to a specific value if the input parameter $top is equal to 1. It is not setting $topspace to a value otherwise, so, if that function gets called with any other value for $top, $topspace is undefined and produces an error when used in building the string that’s being echoed.

For the context of this problem, the solution is to fix the logic to always define/set $topspace to a value. The simplest change to the existing code is to set it to an expected default value, an empty string in this case, before the conditional statement that is setting it if $top is equal to 1.

A short-cut method exists for simple conditional logic for this type of problem -

$topspace = $top == 1 ? " margin-top: 5px;" : '';

For the context of this problem, this isn’t an issue with variable scope. it is an issue with the programmer didn’t do anything to cause the variable to exist and have an expected value when the conditional logic is false.

I’d have to look up what you typed is doing. I understand now the original and adding a default value of topspace. I don’t get the question thing and all you’re doing there. I’ll have to look it up to try to understand.

you can start to lookup my answer first (and take a good look at the example code. Try to understand that the code inside the if statement never will be executed when the result of the if statement equals to false.) , if that works you can read the answer from phdr again and try the short-cut method which is just another way to get done what you want. If you like it: use it. If not then you don’t have to use it.

Sponsor our Newsletter | Privacy Policy | Terms of Service