Yesterday, I posted an answer to a question that included several (unknown to me at the time) very bad code examples. Since then, I've been looking at my fundamental knowledge of PHP that allowed me to think that such code is possible. This brings me to a question that I can't seem to find an answer to:
If I want to check for whether or not a variable has anything set, is it a valid practice to not use isset() or another helper function? here's a "for instance":
if($not_set){
//do something
} else {
//do something else
}
Rather than...
if(isset($not_set)){
//do something
} else {
//do something else
}
From the name of the variable, you can see that this variable is not set. Therefore the conditional would be false and the else portion would run. Up until now I have been using this practice, but after the posts yesterday, I now have an inkling that this is wrong.
Here's why I thought that it would be an ok practice to leave out the isset() function above. From PHP manual:
The if construct is one of the most
important features of many languages,
PHP included. It allows for
conditional execution of code
fragments. PHP features an if
structure that is similar to that of
C:
if (expr) statement
As described in the section about
expressions, expression is evaluated
to its Boolean value. If expression
evaluates to TRUE, PHP will execute
statement, and if it evaluates to
FALSE - it'll ignore it. More
information about what values evaluate
to FALSE can be found in the
'Converting to boolean' section.
And from the 'Converting to boolean section':
When converting to boolean
, the following values are considered
FALSE:
...
* the special type NULL (including unset variables)
Why would the manual go out of its way to state that unset variables are included if this is a bad practice? If it's unset, it gets converted to NULL and therefore is evaluated properly by the conditional. Using isset() will find the same result, but will take extra cycles to do so.
Have I been wrong this whole time, and if so, why? (And just how bad it is, maybe?)
If the variable is not set you get a Notice. If you use isset() you don't get a notice. So from an error reporting point of view, using isset() is better :)
Example:
error_reporting(E_ALL);
if($a) {
echo 'foo';
}
gives
Notice: Undefined variable: a in /Users/kling/test on line 5
whereas
error_reporting(E_ALL);
if(isset($a)) {
echo 'foo';
}
does not output anything.
The bottom line: If code quality is important to you, use isset().
It's okay but not good practice to use if to check for a set variable. Two reasons off the top of my head:
Using isset makes the intent clear - that you're checking whether the variable is set, and not instead checking whether a condition is true.
if ($not_set) will evaluate to false when $not_set is actually set but is equal to boolean false.
You will run in to problems if your variable is set, but evaluates to FALSE, like the following:
the boolean FALSE itself
the integer 0 (zero)
the float 0.0 (zero)
the empty string, and the
string "0"
an array with zero elements
an object with zero member
variables (PHP 4 only)
the special type NULL (including
unset variables)
SimpleXML objects created from empty
tags
Taken from the PHP manual.
Basically, using isset() is showing that you are explicitly checking if a variable exists and is not NULL, while the structure of your if statement only checks if the variable is true. It is more clear and less error-prone.
It is a common practise, but is not good -- you should always use isset!
If your $not_set is set, and is a bool with the value false, your "test" will fail!
isset works as a guard preventing you from using variables that do not actually exist.
if (isset($foo)) and if ($foo) do not mean the same thing. isset just tells you if the variable actually exists and if it's okay to use it, it does not evaluate the value of the variable itself*.
Hence, you should usually use one of these two patterns:
If the variable is sure to exist and you just want to check its value:
if ($foo == 'bar')
If the variable may or may not exist, and you want to check its value:
if (isset($foo) && $foo == 'bar')
If you're just interested that a variable is set and evaluates to true, i.e. if ($foo), you can use empty:
if (isset($foo) && $foo)
// is the same as
if (!empty($foo))
* it does check for null, where null is as good as not being set at all
Related
I am maintaining some old PHP code and I find many places in the code a test for a variable being non-empty of the following form:
if (!(isset($field_name) && strlen($field_name) > 0))
To my way of thinking, the following much simpler form would do exactly the same thing:
if ($field_name)
Am I missing some subltety whereby the more complex form is more precise? I have tended to use the simpler form any place where I need to add new code.
You can use empty() to replace your first line:
if (!empty($field_name))
The problem with your second example is that it will generate a warning if the variable is not set. Both empty() and isset() will not generate a warning for non-existing variables.
Note that you always have to account for possible values so if your value can be 0 or '0', this will not work as after $var = 0;, empty($var) will evaluate to true.
if ($field) will fail if $field is null, 0, 0.00, false or anything that can be casted false
if(!isset($field))
will fail if $field has not been declared at all
They do not do the same thing. The first code sample:
Checks if $field_name exists (I figure the ! is unintentional as it doesn't make sense the way it is written)
Checks if $field_name has a string length greater than zero
The second code sample:
Checks if the variable has a Boolean true value
Will throw an error if $field_name is not set.
The first snippet is clear and precise in its intent and performs a specific task.
The second snippet is very basic and only verifies the variable has a Boolean true value (and there are better ways to do that). If $field_name contains a string "0" this snippet will cause a hard to spot bug as it will fail as "0" evaluates to false. The first snippet would catch this.
You are right that the code you found is odd. It should probably be either:
if(!(isset($field_name)) { ... do something }
or
if(isset($field_name) && strlen($field_name) > 0 ) { ... do something }
...As you can appreciate, there is no need to test the length of a variable that is not defined.
However, if($field_name) is not the same as if(!(isset($field_name)), and the difference is not subtle. Indeed, the former will earn you a Undefined variable: fieldname if by some stroke of bad luck $field_name is not defined.
What's the difference?
if($field_name) tests if the existing variable $field_name evaluates to TRUE. For instance, it's value might be "my dog", and that evaluates to TRUE
if(!(isset($field_name)) tests if the variable $field_name exists at all.
There is an example in PHP Object-Oriented Solutions that seems to be flawed, if I understand is_null properly.
The sample code in the book is as follows:
if (!is_null($required) && !is_array($required)) {
throw new Exception('The names of required fields must be an array, even if only one field is required.');
}
This code is supposed to test that a var $required is not NULL and is an array. To my understanding, is_null() returns TRUE if the variable is not set or is NULL. So, does it make sense to negate is_null() in that example if you're trying to throw an exception when the variable is not set, NULL, or is not an array? The only way an exception is thrown is if (true && true) is satisfied.
FROM: http://www.php.net/manual/en/language.types.null.php
A variable is considered to be null if:
it has been assigned the constant NULL.
it has not been set to any value yet.
it has been unset().
<?php
if(is_null($obj)){
echo 'is null';
}
While $obj is considered NULL because it hasn't been registered yet, it will still throw a Notice: undefined ...
The correct use for your if statement should first check to see if the variable exists then check to see if it is an array.
if (!isset($required) || !is_array($required)) {}
-or-
if (empty($required) || !is_array($required)) {}
The nice thing about is_array() is the fact that if $required IS NULL then it's not an array and will pass the if clause.
isset() and empty() will both ensure that the variable exists. Failure to pass either of these methods will quit the if statement and no errors will be returned.
I appreciate all the feedback, but somehow I think part of my question was not addressed. The fact that the variable is being tested with a Logical AND, means that both statements must be TRUE for the Exception in the if clause to run.
But, I don't think the use of !is_null($required) is correct. The sample code from the book was testing for a variable to contain an array with one to many values. Even if it has one value, the $required variable (for other reasons) still must be declared as an array with a single value. So, if $required hold's a value of (int) 5, an Exception should be thrown. If the $required variable is not declared/instantiated, an Exception should be thrown. If the $required variable holds NULL, an Exception should be thrown. Here is where the logic of this sample code fails. Using the online php command line that #Calimero posted, this logic fails when $required is set to NULL.
Instead of using !is_null($required) , is_null($required) without the negation should have been used since is_null returns TRUE if the value of $required is indeed NULL. So, if you negate is_null() when the $required value happens to be NULL, that part of the logical AND operation becomes FALSE, therefore the Exception never gets run at all because the logical AND operation requires both statements to be TRUE for the logic to jump into the curly braces. Which is precisely what the if clause was supposed to catch in the first place. The sample code was supposed to catch the $required variable not being set and not being of an array type.
And as I mentioned in a comment, isset() probably wasn't used because isset will return TRUE even if the $required variable is an empty string, a string with a space, an empty array, etc.
Someone please confirm I'm not talking stupid. LOL.
Take a look at this: (http://3v4l.org/QpVXq)
**Is_null**
The is_null is php construct language and can be used to test whether a variable is set to null.
$myVariable = null;
is_null($myVariable); // this returns true,because it is set to null
$myVariable = 10;
is_null($myVariable); // this returns false, cuz it is assigned to value
If the variable does not exist is_null will also return true,
but with an error notice as it is not supposed
to be used with uninitialized variables.
//returns true and also notice with (undefined variable notice)
is_null($myNewVariable);// true (undefined variable notice)
If the code is part of a function, it could be that the function allows for null values, but if the value is passed and it's not an array, then an exception must be thrown. If the code is not part of a function, it may be just demonstrating how to detect if a value is an array only if it isn't null, thus allowing null values.
In PHP, what is the difference between:
if($might_not_be_set) doStuff();
and:
if(!empty($might_not_be_set)) doStuff();
The former approach clutters the Apache logs with undefined variable notices, but I don't see the reason to not use it - what does it do differently?
PS. I don't want to use isset() - evaluating as a boolean is exactly what I want.
empty() will evaluate a zero length string or NULL to TRUE while any longer string (or integer or boolean) will be FALSE. Therefore, your !empty() will just make sure that there is some value in there, not necessarily the one you want..
For example, an empty() check of the strings 1, false, and true all evaluate to FALSE while a string of 0 will evaluate to TRUE.
I suggest that whatever you use, you should be painfully explicit for the next guy on what you are/aren't expecting.. even if that's just you six months from now.
Here's a detailed comparison:
http://php.net/manual/en/types.comparisons.php
You said it yourself: the first method clutters the logs with warnings about undeclared variables. Both methods are functionally equivalent, but it never hurts to be explicit. I would go with the !empty() because it is both explicit and avoids the clutter.
empty() determine whether a variable is considered to be empty. A variable is considered empty if it does not exist or if its value equals FALSE. empty() does not generate a warning if the variable does not exist.
http://php.net/manual/en/function.empty.php
I noticed this weird evaluation yesterday after searching for a few hours in my code for an error. i am passing scores into php, sometimes the score=0 which causes an issue.
send php ?blah=blah&score=0
if(!empty($_REQUEST['score']){
//do database update stuff
}else{
// show entire webpage
}
It works great unless the score=0 the if() will evaluate to false and return the entire webpage to my ajax handler and error. I have temporarily changed !empty to isset but this will cause problems in the future because isset evaluates to true even if the score key is in the url string without a value.
ex: (?blah=blah&score=&something=else)
my question is: what is the best way to recode this to work correctly now and in the future?
edit: there are a few working answers here, i appreciate everyones time. it was difficult to choose an answer
As the manual says, a variable is considered empty() if it has an empty or zero value.
So it will treat your variable wrongly as empty even though 0 is a perfectly acceptable value in your case.
If you need score to be a number, you could use isset() in combination with a is_numeric() check instead:
if((isset($_REQUEST['score']) and (is_numeric($_REQUEST['score'])){
Check out the manual page to see the kinds of values is_numeric() accepts. If score is always an integer, you can also use is_int((int)$_REQUEST['score']) but that will convert invalid input values to 0.
Additionally, as #sightofnick says, it's better to use explicit $_GET or $_POST instead of $_REQUEST.
Re your update:
In that case I would
Do check whether the variable is "0" (string "zero")
If it is "0", make it 0 (integer "zero")
If it is not 0, convert it to an integer (int)$_REQUEST["score"])
If the conversion resulted in 0, it was invalid input - exit
You have a valid integer variable.
empty() will return false if a value is zero. Use isset() or array_key_exists() instead, if you want to check if a variable in an array is set:
if (array_key_exists('score', $_REQUEST)) {...}
Try doing
if (isset($_REQUEST['score']) && ($_REQUEST['score'] !== '')) {
...
}
The isset will handle the presence/absence of the query parameter, and the strict string (!==) comparison will handle the case where the 'score' query is present but has no value. PHP treats all data coming from _GET/_POST/_REQUEST as strings, so this test is 100% reliable.
if(isset($_REQUEST['score']) && $_REQUEST['score'] != ''){
//do database update stuff
}else{
// show entire webpage
}
You may be able to solve that with
if (isset($_REQUEST['score']) && is_numeric($_REQUEST['score'])) {}
That of course if scrore can only contain numeric value
I am new to the concept of empty and null. Whilst I have endeavoured to understand the difference between them, I am more confused. I came across an article at http://www.tutorialarena.com/blog/php-isset-vs-empty.php however I still don't see when you would use isset and empty when validating forms. Seeing that I don't grasp the difference, I don't want to be using the incorrect functions as well as not be able to use the functions in other areas. Can someone give examples that will help me understand? I am very new to coding so would appreciate if someone could give me real world examples and at the same time keep it simply enough for noob to follow.
A variable is NULL if it has no value, and points to nowhere in memory.
empty() is more a literal meaning of empty, e.g. the string "" is empty, but is not NULL.
The following things are considered to
be empty:
"" (an empty string)
0 (0 as an integer)
0.0 (0 as a float)
"0" (0 as a string)
NULL
FALSE
array() (an empty array)
var $var; (a variable declared, but without a value in a class)
Source.
Example
$a is NULL.
$a = '' is empty, but not NULL.
Update
If $a='' is empty but not NULL, when do I use the empty() function and when do I use the isset() function.
isset() will return FALSE is the variable is pointing to NULL.
Use empty() when you understand what is empty (look at the list above).
Also when you say it points nowhere in memory, what does that mean exactly?
It means that $str = '' will be in memory as a string with length of 0.
If it were $str = NULL, it would not occupy any memory.
Null is a placeholder that generally means "no data about this is available".
The use of null for this is just a convention, but a rather widespread one, to the point where some programming languages support the convention directly. The reason this convention exists has IMHO historically to do with "pointers";
many times a procedure will be defined to return a pointer to an answer, and will return what is traditionally called a Null pointer if it could not produce an answer for some reason.
Empty means (if this is a set) that it has no members. That's an explicit answer, and it is very different than "no data about this is available".
In the PHP world, apparantly uninitialized variables have the Null value, and isset on such a variable returns FALSE.
For arrays and strings, PHP follows the convention that "empty" means "has no members" although arrays and strings are not technically sets.
PHP apparantly has this funny idea that 0 and 0.0 are also "empty", by PHP design. That's abusive of the concept of "empty" IMHO: Individual numbers are not sets, so 0 can't reasonably by "empty". THis just leads to obscure programming because it violates the principle of least surprise. I'm sure the PHP designers would are that "zero is the empty number" as some kind of vague analogy; but the if analogy is vague, why bother with it? But then PHP is full of silly ideas.
The table below is an easy reference for what these functions will return for different values. The blank spaces means the function returns bool(false).
refer this link for more https://www.virendrachandak.com/techtalk/php-isset-vs-empty-vs-is_null/
NULL is a special value which explicitly states that the variable has not been set to any value yet. Be careful with using the empty() function as you can't just determine that a variable is exactly NULL using it. For example the empty() function will return true if an int is set to 0. If you need to make sure a variable is exactly NULL use if($variable == NULL).
For more info on empty() see http://php.net/manual/en/function.empty.php
There are some good answers here, which I won't repeat. In the case of validating forms, though, when a form is submitted, the value of each form input element is sent to the server in the $_POST variable. You can check for the existence of a particular input by using isset().
isset($_POST['username'])
If this returns true, then this request to the server was the result of posting a form containing an input element named "username". Now that we know that we have a value for that form element, we can see if it has a valid value. empty() will tell us whether the user actually entered any data in the field, or whether they left it empty.
empty($_POST['username'])
If that returns true then the form submitted to the server had a field named "username" but the user didn't enter anything into before submitting the form.
Been awhile since i used PHP but if other languages are anything to go by empty will indicate an existing object/map/array that has no contents while null would indicate a variable that has no meaning/definition at all (uninitialised).
In database SQL, NULL means "no value".
The empty() is a nice fast way to see if the variable holds any useful info... that is for strings empty() returns true for a string of "" as well as a null string.
So you can write something like this:
if (! empty($name)) echo $name;
More info see here: PHP: empty()
isset() returns true if both these conditions are met:
The variable has been defined and has not yet been unset.
The variable has a non-null value in it.
A variable is automatically defined when it gets set to something (including null). This has a direct implication in arrays.
$a=array();
$a['randomKey']=true;
$a['nullKey']=null;
var_dump(isset($a['randomKey'])); // true
var_dump(isset($a['nullKey'])); // true, the key has been set, set to null!
var_dump(isset($a['unsetKey'])); // false !
unset($a['randomKey']);
var_dump(isset($a['randomKey'])); // false ! it's been unset!
From above, you can check if various $_POST fields have been set. For example, a page that has been posted to, stands to reason, has the submit button name in the $_POST field.
empty() on the other hand, tests if the variable holds a non zero value. This means that values that (int) cast to 0, return false too. You can use this to see if a specific $_POST field has data in it.
This concept can be better understood from mathematics. Have you ever tried dividing a number (not zero) by 0 using a calculator e.g 7/0? You will get a result that looks like something this: undefined, not a number, null etc. This means that the operation is impossible, for some reasons (let's leave those reasons to be discussed another day).
Now, perform this: 0/7. You will get the output, 0. This means that the operation is possible and can be executed, but you the answer is just 0 because nothing is left after the division. There is a valid output and that output is zero.
In the first example, not only was the output invalid, the operation was not possible to execute. This is akin to null. The second example is akin to empty.