Difference between boolean evaluation and !empty in PHP - php

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

Related

checking if a string variable has data in it, which one is better !empty() or '!'

it occured to me that some people prefer to use !empty($val) over !$val to check a strings existance. what are the advantages of using !empty() over ! if any?
lets assume string can be:
null
""
"false"
"1"
"0"
all of the above give the same result in both methods. is there any other case that would cause problems using one instead of the other?
empty($var) vs. !$var a.k.a. $var == false
The only difference is that empty does not throw an Undefined variable notice if the variable does not exist, otherwise they're both identical. Now, if you are sure that the variable should exist, use just !. If the variable may legitimately not exist, use empty. If you needlessly use empty, you're just needlessly disabling PHP's error reporting mechanism which may help you catch problems with mistyped variables or logic errors.
Also see The Definitive Guide To PHP's isset And empty.

Comma Operator PHP

Both these statements are true:
$_POST['foo'] = $_POST['bar'] = 'some string';
//1. with '&&' operator
if(isset($_POST['foo']) && isset($_POST['bar'])) {
echo true;
}
//2. with a comma
if(isset($_POST['foo'], $_POST['bar'])) {
echo true;
}
What is the difference (if any) between them?
There IS a difference, in practice. The meaning should be the same, however the "comma operator" version implements a "complete boolean evaluation" in this case. That is, if the first variable is not set, php won't look at the second since they're in a && relationship and the result can't be true anymore. (This is called a "short circuit" eval) In the second case, php must calculate both arguments before calling isset(...) so both values will be checked.
It's just the principle, yes, but sometimes it's very important, for example if the operands are function calls.
(Just a short reply to the commenter saying "isset does not take function calls" - it's not about isset, it's about implementing expressions in general. Stop calculating things as soon as the result is obvious, and spare yourself as many partial results as you can. Function arguments will do the opposite: they all get calculated before they get passed to the subroutine.)
There's no difference according to the PHP documentation: isset() function. Indeed, isset can take an infinity of argument and returns true if every variable passed exists. It's similar to test if each isset() of each variable is true.
The theory should be check, but the function takes only variable in argument as said by the doc:
isset() only works with variables as passing anything else will result in a parse error. For checking if constants are set use the defined() function.
... So there's no problem about priority of the compute of arguments.
Finally, be aware that the comma here isn't an operator. The comma here is used to separated arguments of the isset function. The previous explanation doesn't work with empty() for example since the empty function only takes 1 argument.
TL;DR: isset($a, $b) == isset($a) && isset($b), but empty($a, $b) is a syntax error.
The isset() function can accept multiple arguments. If multiple arguments are supplied, then it only returns true if all of them are set.
http://www.php.net/manual/en/function.isset.php
There's no difference, except for the fact that you are calling isset() twice in 1., effectively evaluating both returning values with the && operator, in 2. you are just using isset() with two arguments instead of one, separated with a comma.

Condition comparing string against bool returning undesired result unless strict comparison is used

In PHP 5.3, i stumbled upon this case:
$test=true;
return $test=='alternate';
It returns true. I do not understand why.
Why does it return true?
Additionally it is to say that:
$test=true;
return $test==='alternate';
Returns false. Rightfully so. I am aware that it is better to use strict comparison in most cases, but i would like to understand what happens in the first case?
Non-empty strings are considered to be true. Loosely comparing true with true yields true.
See http://www.php.net/manual/en/types.comparisons.php for details. And always use strict comparisons. You rarely ever need loose ones, but in every case you induce the doubt whether you meant to type-cast the variables or if it is an error.

PHP - isset($variable) and notices

so if I have this code:
$bla = 1;
if($foo && $bla) do_whatever...
I get a notice telling me that $foo is a undefined variable.
So I have to change my code to this:
$bla = 1;
if(isset($foo) && $foo && $bla) do_whatever...
Is there anyway I can avoid checking if a variable is assigned and just assume the variable is false, but without having to turn off PHP notices?
Depending on the exact behavior you want, you can check if the variable is empty():
Returns FALSE if var has a non-empty
and non-zero value.
The following things are considered to
be empty:
"" (an empty string) 0 (0 as an
integer) "0" (0 as a string) NULL
FALSE array() (an empty array) var
$var; (a variable declared, but
without a value in a class)
It's important to understand all those cases, but it's handy language construct. if $foo is undefined if($foo) will throw a notice, but if(!empty($foo)) will not -- the expression will evaluate to false
This should not be abused, however. As others have stated, those notices are for your protection, so if you can define your variables, you should do so. Where empty() comes in especially handy is things like if (!empty($_GET['foo'])) - testing for the existence of input in superglobals.
The entire point of notices is to tell you that something might be wrong (such as writing $fooo instead of $foo). So, if you're not going to use them, you might as well disable them. You can disable a notice selectively by setting your own error handler, and discarding the error silently when it's of the "undefined variable" kind.
Of course, the clean thing to do would be to define your variables in the first place.
No, there isn't.
No, you should always know exactly what's going on with your variables. In fact, you should never need to use isset() on a variable itself at all.
You could do:
if(#$foo && $bla) do_whatever...
The # will suppress the warning.
But you really shouldn't do it. Not checking ALL your input is just plain WRONG.

Is this an OK test to see if a variable is set

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

Categories