Reputation:
According to the manual:
Parentheses may be used to force precedence, if necessary.
However, it seems && remains higher:
$var = null;
var_dump($var && ($var->a() || $var->b()) && $var->c());
I expect ($var->a() || $var->b())
to be evaluated first, due to the brackets, and throw an error for the missing method. However, the result is bool(false)
with no error. How so?
Upvotes: 0
Views: 156
Reputation: 16103
Not the full statements gets checked
function A (){ echo "ran A\n"; return false;}
function B (){ echo "ran B\n"; return true;}
if( A && B ){
echo 'Both true';
} else{
echo 'One or both false';
}
Both must be true, but A isn't true, why bother checking the rest? No matter what B
returns, the statement will never be true and it will be the else{} (and get 'ran A' and NOT get 'ran B').
Also, precendence gets prioritized with brackets, but it still goes from left to right:
if( A && (B or C) && D)
A
will run. If it's false, no point in continueing. B/C/D dont runA=true
B
will run.
B=true
C
wont run, as only one true is needed. Then D
is runB=false
C
will run
C=true
D
is runC=false
(and B
also is) the inners of the parenthesis are 2xfalse -> false. D
wont run as it wont matterWhen you understand this concept, you can use this trick to your benefit. An example with the ??
operator:
$thing = $user->getThing() ?? $user->makeNewThing();
You try to get $thing from the user object. If it exists you get it and makeNewThing()
never gets called (as it would be useless, to optimized away). If ity doesnt, only then it gets ran.
Upvotes: 0
Reputation: 4717
From the official PHP documentation:
// foo() will never get called as those operators are short-circuit
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());
Upvotes: 3