Jump to content

PHP Upgrade from 5.5.38 to 5.6.33


iwato

Recommended Posts

BACKGROUND:  I recently upgraded my version of PHP from 5.5.38 to 5.6.33.  PHP code that functioned perfectly well now fails with imposed notifications complaining about undefined variables.  Mind you, my error logs and notifications are turned off.  This suggests that I must either learn how to turn off these imposed intrusions or learn to write PHP properly and modify all of my PHP processing files accordingly.  In the belief that I will be better served by the latter, I am appealing to W3Schools to set me straight.

REQUEST:  Please examine the following two pieces of code and correct then so that I do not receive a notice from PHP telling me that the variable is undefined, when indeed no value was intended.  This is just a sampling of the problem that I am now confronted with.

Sampling One - The CODE
My Action:  I selected webinar, but not newsletter before the form was submitted.

<?php
//		ini_set('display_errors', 1);
//		ini_set('display_startup_errors', 1);
//		error_reporting(E_ALL);	
		require_once '../../_utilities/php/php_mailer/PHPMailerAutoload.php';
//		var_dump(class_exists('PHPMailer'));
		$name = $email = $newsletter = $webinar = $language = $error_msg = '' ;
/*		function test_input($data) {
		  $data = trim($data);
		  $data = stripslashes($data);
		  $data = htmlspecialchars($data);
		  return $data;
		}
*/		if ($_SERVER["REQUEST_METHOD"] == "POST") {
			if (empty($_POST['language'])) {
				$error_msg = "Please select your first language or add another, if yours is not listed.";
			}
			else if ($_POST['language'] == 'other_tongue') {
				if (empty($_POST['other'])) {
					$error_msg = "Please enter your first language.";
				} else {
					$language = filter_var($_POST["other"], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
				}
			}
			else {
				$language = filter_var($_POST["language"], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
			}
			if (!($_POST["newsletter"]) && !($_POST["webinar"])) {
				$error_msg = "Have you forgotten to select a gift?";
			} else {
				$newsletter = filter_var($_POST["newsletter"], FILTER_SANITIZE_NUMBER_INT, FILTER_VALIDATE_INT);
				$newsletter = !empty($newsletter) ? "$newsletter" : 0;
				$webinar = filter_var($_POST["webinar"], FILTER_SANITIZE_NUMBER_INT, FILTER_VALIDATE_INT);
				$webinar = !empty($webinar) ? "$webinar" : 0;
			}
			...

The ERROR MESSAGE:

Quote
( ! ) Notice: Undefined index: newsletter in /Users/kiusau/Sites/grammarcaptive.com/_gates/gate7/gate7d.php on line 28
Call Stack
# Time Memory Function Location
1 0.0021 276464 {main}( ) .../gate7d.php:0

 

( ! ) Notice: Undefined index: newsletter in /Users/kiusau/Sites/grammarcaptive.com/_gates/gate7/gate7d.php on line 31
Call Stack
# Time Memory Function Location
1 0.0021 276464 {main}( ) .../gate7d.php:0

 

Sampling Two - The CODE
My Action:  I opened the page directly.  There was no referral.

<?php

/*	ini_set('display_errors', 1);
	ini_set('display_startup_errors', 1);
	error_reporting(E_ALL);
*/
	if (filter_var($_GET['refer_type'], FILTER_VALIDATE_INT)) {
		$refer_type = $_GET['refer_type'];
	} else {
		$refer_type = 0;
	}
	...

The ERROR MESSAGE:

Quote
( ! ) Notice: Undefined index: refer_type in /Users/kiusau/Sites/grammarcaptive.com/overview.html on line 7
Call Stack
# Time Memory Function Location
1 0.0519 247752 {main}( ) .../overview.html:0

Please advise.

Roddy

Edited by iwato
Link to comment
Share on other sites

Anytime you're checking for input values in POST, GET, or COOKIE you should use isset () to check that they exist before doing any operations with them. This is not new to PHP. My guess is that previously you had warnings turned off. Using empty () also works since it uses isset () internally. 

  • Like 1
Link to comment
Share on other sites

I am a little confused by your answer:

1) Recall that all I did was upgrade from PHP version 5.5.38 to 5.6.33 on my local server.

2) Further, understand that my error reporting was turned off both before and after the upgrade, and that the error messages only began appearing after the upgrade.

3) In addition, please note that my 3rd-party host server, where the relevant PHP files are set identically with those on my local test server, also uses 5.6.33.  There, no error messages are reported.

Finally, I do not understand why the following code produces the undefined notice.

	if (filter_var($_GET['refer_type'], FILTER_VALIDATE_INT)) {
		$refer_type = $_GET['refer_type'];
	} else {
		$refer_type = 0;
	}

My UNDERSTANDING:  If there is a value registered for $_GET['refer_type'], the variable is obviously set, and the value is assigned to $refer_type.  If there is no value, it matters not whether the variable is set or not, for the value 0 is assigned to $refer_type, no matter whether $_GET['refer_type'] is set or not.

REQUEST:  How would you write the same code to avert the error message, if indeed, it is the code that is creating the message and not something else.

 ?

Roddy

Edited by iwato
Link to comment
Share on other sites

Recall that all I did was upgrade from PHP version 5.5.38 to 5.6.33 on my local server.

So what?  I'll bet 10 to 1 that the major change was that your php.ini changed so that PHP is now reporting more errors than it used to.  Referencing undefined variables has been an error for a long, long time.  If you weren't seeing it, your options were set up to ignore those errors.  Ignoring errors isn't a good idea, because like you're finding out you might take your code to a PHP environment that is configured differently and all of a sudden it's emitting all of these notices and warnings that your old server was set to ignore.  You should always develop code with maximum error reporting, and you shouldn't stop until there are no more error messages.

Further, understand that my error reporting was turned off both before and after the upgrade, and that the error messages only began appearing after the upgrade.

The solution is to fix the errors in your code.

In addition, please note that my 3rd-party host server, where the relevant PHP files are set identically with those on my local test server, also uses 5.6.33.  There, no error messages are reported.

I bet they're hiding them!  Not a good idea.  For what it's worth, our applications report all errors, but have display_errors disabled so that users do not see them, but we use error logging to write them all to a file.  So if someone is reporting problems I can go check the log to see the actual error messages that happened when that person was using it.  What I would never even think about doing is just turning off error reporting.

it matters not whether the variable is set or not

That's your opinion.  In practice, if well-written code is trying to refer to an undefined value then it's highly likely that the programmer made an error.  Your code should never produce error messages regardless of error reporting settings.

How would you write the same code to avert the error message

if (isset($_GET['refer_type']) && filter_var($_GET['refer_type'], FILTER_VALIDATE_INT)) {

Link to comment
Share on other sites

Undefined variables and array keys have always been an error in PHP, whether or not the error messages are being hidden. PHP is a very forgiving language, in any other language undefined variables or properties would not even allow the code to compile.

PHP has mechanisms to catch and fix attempts to access unallocated memory, but it comes at a cost, which is why the PHP engine sends warnings every time it fixes these mistakes. The problem with accessing undefined variables or properties is that PHP has to allocate memory for a variable that is never going to be used, the cost being the amount of memory allocated and the amount of processing time required to allocate that memory.

Problems like this are why I would never recommend PHP or Javascript for somebody who wants to start learning programming. They allow the use of undefined variables and the variables do not have a strict data type assigned to them.

Link to comment
Share on other sites

The problem with accessing undefined variables or properties is that PHP has to allocate memory for a variable that is never going to be used, the cost being the amount of memory allocated and the amount of processing time required to allocate that memory.

I don't think that's necessarily true, if you try to access an undefined variable I don't think PHP allocates anything for it in the hash tables, because if you try to access it a second time it does the same thing.

Link to comment
Share on other sites

This is my understanding of your discussion.

  • All variables contained in a superglobal and sent from one document to another should be checked for initialization in the sending document before being processed in the receiving document.
  • All variables that are used out of scope -- namely, globally -- should be initialized (assigned some value or non-value) at the outset.

Is it accurate?

One often sees in both Javascript and PHP the following sort of initialization.  Is it correct?

PHP:  $search_engine =;

and

Javascript:  var searchEngine = ;

Roddy

Link to comment
Share on other sites

All variables contained in a superglobal and sent from one document to another should be checked for initialization in the sending document before being processed in the receiving document.

I'm having problems parsing that sentence.  First, I'm not sure why being a superglobal is significant.  Second, documents don't really send values to each other, PHP works with the web server in a request-response format.  Requests are sent, with any accompanying data, and PHP and the web server produce a response.  This is just the web browser and the web server communicating with each other.

All variables that are used out of scope -- namely, globally -- should be initialized (assigned some value or non-value) at the outset.

Ideally, they should.  It's not always necessary though, or even possible.  You don't initialize variables in $_GET or $_POST, for example.

One often sees in both Javascript and PHP the following sort of initialization.  Is it correct?

No, you need a value on the right side of the assignment operator.

Link to comment
Share on other sites

43 minutes ago, justsomeguy said:

I'm having problems parsing that sentence.  First, I'm not sure why being a superglobal is significant.  Second, documents don't really send values to each other, PHP works with the web server in a request-response format.  Requests are sent, with any accompanying data, and PHP and the web server produce a response.  This is just the web browser and the web server communicating with each other.

"First, I'm not sure why being a superglobal is significant.":  Because the $_GET, $_POST, and $_COOKIE containers that Ingolme mentioned are all superglobals and there are other superglobals such as the $_REQUEST superglobal that do the same thing.  The word "and" in the phrase "All variables contained in a superglobal and sent from one document to another ..." is very important in this regard.

Quote

Second, documents don't really send values to each other, ...

Yes, I understand what you mean, but the end result is a transfer of information between documents.

Quote

You don't initialize variables in $_GET or $_POST, for example.

OK.  So, what is the point of asking whether or not the variable has been defined?  Are you suggesting that all form input controls -- be, they select, input, textarea or whatever -- should be assigned a default value before being sent?

Roddy

 

 

 

Link to comment
Share on other sites

Because the $_GET, $_POST, and $_COOKIE containers that Ingolme mentioned are all superglobals and there are other superglobals such as the $_REQUEST superglobal that do the same thing.

I understand that, I understand what superglobals are.  But when you're talking about checking if a variable is defined, whether or not it is a value in a superglobal is completely irrelevant.  That is, the rules that you should follow for checking if things are defined before you use them are no different based on what kind of value you're dealing with.  It doesn't matter that it's a superglobal.

Yes, I understand what you mean, but the end result is a transfer of information between documents.

No it's not, it's important to fundamentally understand what's going on.  Normally PHP documents do not communicate with each other.  The web browser, not a PHP document, sends a request to the web server.  It's important to understand that.  PHP files do not directly communicate with each other unless you're doing something like sending a cURL request from one PHP file to another PHP URL, but even in that case it's still sending an HTTP request.  It might just be terminology, but it's important to understand how the request/response cycle is the foundation of PHP running on a web server.  Specifically, you need to keep in mind that your web browser is what is sending data to your server, it's not one PHP page on your server sending data to another one.

Are you suggesting that all form input controls -- be, they select, input, textarea or whatever -- should be assigned a default value before being sent?

Whether form controls have a default value has nothing to do with checking what data came from a form.  You should still check for the presence of any value that you are going to reference, that should be part of form validation.  If your form has a zip code field, don't just assume it came with the rest of the form, check for it.  Maybe someone is messing with your server looking for vulnerabilities (even in that case, your code should not emit errors), maybe you made a new form page and forgot a field, etc.

So, what is the point of asking whether or not the variable has been defined?

For the simple purpose that you know you're not using any undefined variables, and that your code is not producing errors (even if you're ignoring them).  It's really that simple, there's not a lot to think about here.  When processing user-submitted data, just verify that it's set before using it.  That's all there is to it, there's not much philosophy behind this.  Just check if things got submitted instead of assuming they were, that's all it is.

Link to comment
Share on other sites

I will not bother with the topics in which we are talking past one another, but I do thank you for your insistence that I and whoever else is reading our discussion understands correctly.  Truly it is helpful.  I do want to make clear, however, that I always have error reporting on when I am writing code, and the only reason that the code had been turned off was because the document functioned in the end as I wanted.  Clearly, though, an error, a notice, and a warning are three different kinds of messages, and never before have i had my code interrupted by a notice or a warning.  Hence, my concern.

I am still unclear about one matter.  It would appear that a superglobal  is fundamentally an object-type variable that contains property-value pairs.  The requirement that I check every key-value pair appears, therefore, excessive.  This suggests that superglobals are, indeed, a special kind of variable -- neither an array, nor an object.   And this, despite the fact, that in many cases they behave identically to an object or an array.  Is this a proper understanding.

Roddy

Link to comment
Share on other sites

Superglobals are literally PHP arrays. The only difference between a regular PHP array and a superglobal is that the superglobal is accessible from any scope. You can read all the details about arrays here: http://php.net/manual/en/language.types.array.php

In PHP, arrays behave similar to the map structure in other languages.

Here's a PHP sample of managing an array. not necessarily a superglobal, just any array.

<?php
$data = [];
if(isset($data['something']) && $data['something'] == 'value') {
  echo 'The array contains the key "something" with value "value"';
}
?>

Here's the same code using a map in Java:

Map<String,String> data = new Map();
if(data.containsKey("something") && data.get("something").equals("value")) {
  System.out.println("The map contains the key \"something\" with the value \"value\"");
}

Notice that in both cases, we see whether the key exists before trying to retrieve a value associated with the key.

  • Thanks 1
Link to comment
Share on other sites

I agree that array superglobals in PHP act no differently than any other array.  The only difference between a superglobal and any other variable is an entry in one of PHP's internal tables that keeps track of scope, where a superglobal is always in scope.  That's the only difference.  It is not a different kind of data type than you can use in any other part of PHP.  That's why I was saying that it does not matter that it's a superglobal, you check for the existence of values the same way as you do with any other array.

The requirement that I check every key-value pair appears, therefore, excessive.

Why is that excessive?  Do you think there should be a way to check all of the keys at once, and if so, how do you do that?  Don't you have to check each one individually no matter how else you do it?  If you want to write a function to take an array and a second array of keys, and return true or false if the first array contains every key in the second array, you can do that, but I don't know what the big deal is.  It's not like I'm spending a lot of time checking if array keys exist, that's a small part of programming.  This is probably the largest discussion I've ever had about checking if array keys exist, it's just not a big deal to verify that things exist before trying to use them.  You have the isset function for most cases, and the empty function for the case where you're trying to check if the value exists and contains a non-falsy value.

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...