isset() and NOT operator - php

I know about questions like this one. There are lots of them with great answers.
I know this was "fixed" in PHP 5.5.x, but I'm unfortunately I'm using 5.3.x.
$iHatePHP = $node->get($key);
if (isset($node->get($key)) ...
The error I get:
Fatal error: Can't use method return value in write context in ...
I know the "fix" is to put the result of get() into a variable and call isset() on that. However, in order to save writing that thousands of times in my code, is it equivalent or am I missing some cases?
$iHatePHP = $node->get($key);
if (!($node->get($key)) ...
Edit: I control get(). So I can make it return anything I like, such as NULL, FALSE or ""

The isset() pseudo-function checks not for a variable that would cast to false, but for one which is null. Additionally, it checks for a variable or array key's existence; a non-existent variable would be null anyway, but would also issue a Notice, in case you had mistyped the name or similar.
When you are testing the result of a function or method call, you know that there is some return value (a function with no return statement, or a plain return; with no value, is returning null), so the extra case of "no such variable" is impossible. The easiest way to test the value is therefore is_null:
if ( is_null($node->get($key)) ) ...
If $node->get($key) returns false, 0, or '', the ! version would enter the if statement due to the rules on converting other types to boolean.
The similar empty() construct does evaluate as though you had applied a ! operator, but preserves the special behaviour for non-existent variables - empty($foo) is effectively the same as ! isset($foo) || ! (bool)$foo.

Related

PHP Shorthand ifelse understanding

I am trying to make some sense out of the following shorthand
$state = $account->getCity() ? $account->getCity()->getStates() : null;
Is my understanding right?
if $account->getCity() exist assign the value of $account->getCity()->getStates() to the $state variable else assign is null
Reason I am asking this is because I m getting the error
Error: Call to a member function getCity() on a non-object
If the code $state = $account->getCity() ? $account->getCity()->getStates() : null; does not check to see if $account->getCity() is null then how do I make it so it checks it.
The output I am trying to achieve is
if $account->getCity() is not null assign the value of $account->getCity()->getStates() to the $state else just make it null
Hopefully I am not sounding too confusing :)
You're currently using what is known as "ternary operator" shorthand. However, you're using the $account->getCity() method to try and check if $account->getCity() exists, resulting in the problem.
A better practice would be to use isset($account->getCity()) or (!empty($account->getCity())) to evaluate if it exists. It is worth noting that isset() will check if it exists, where as empty() will check if it exists AND is filled with a value. As comments mention, you may also need to check that the object is actually an object, which can be done with is_object($object), such as using (is_object($account) && !empty($account->getCity()).
A common issue seen is that a variable or object may be assigned, but the contents are empty, similar to using $variable = '';. Checking using empty() may save you the heartache of coming across this problem down the road.
An additional side note is that while ternary operators are fantastic, they are best used when both a true and false condition are supplied. If you insist, try to at least use null in place of '' in the operation.

Correct way to use !is_null()

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.

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.

Ternary if statement involving php class

Can someone please explain to me the following line of php?
($myobjectfunction = object::function('letsgo')) ? eval($myobjectfunction) : false;
I understand objects and their functions. Is this php saying if $myobjectfunction is defined then eval $myobjectfunction, otherwise do nothing? Because in the code I am reading, object hasn't yet been defined before this line (sometimes).
This line assigns the returned value from the function object::function('letsgo') to the variable $myobjectfunction. If the return was a "truthy" value (evaluates to boolean TRUE), the contents of that variable are then evaluated as PHP code (eval). If the initial return was FALSE, no further action is taken. The false at the end basically does nothing.
This works because PHP will return the value from an assignment, even though it isn't usually used for anything. In the case of your bit of code, however, the return from the assignment is used to determine which branch of the ternary operator to take since it is enclosed in parentheses.
$x = 3;
// returns 3 even if we don't use it...
This is an unusual idiom, because the parentheses are around the initial assignment.
($myobjectfunction = object::function('letsgo')) ? eval($myobjectfunction) : false;
//^^---------------------------------------------^^^
A more typical usage of the ternary operator would assign the output of either side of the ? to the variable on the left, based on the condition to the right of the = like:
$myobjectfunction = object::function('letsgo') ? $someothervalue : false;
It's difficult to tell exactly what's going on here. I'm assuming you have substituted actual values in order to 'simplify' the example, but the use of keywords actually clouds the matter.
The declaration of the class 'object' doesn't need to be before this statement, so long as the object class is defined at some point during the code execution.
This code is equivalent to:
$myobjectfunction = object::function('letsgo');
if( $myobjectfunction ) {
eval( $myobjectfunction );
}
else {
false;
}
In other words, assign the result of object::function( 'letsgo' ) to a variable. If that variable is "truthy" (i.e. not false, null, or 0, or another value that evaluates like false) then eval its contents; otherwise do nothing.
ya you pretty much got it, well its saying IF $myobjectfunction has successfully been returned a positive result (ie: not false, 0, or null) the eval the new variable object, but i probably wouldnt use "false" in the else bit., id probaby use null.
Now for this to do anything, "object" does need to be defined
this is a strange piece of code though, in my own honest opinion

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