- URL: https://www.laruence.com/en/2010/07/26/1668.html
- Please include attribution when republishing.
Today I saw a question on Lao Wang's tech notes:
<?php
if ($a = 100 && $b = 200) {
var_dump($a, $b);
}
What's the output?
At first glance this might look simple, but on closer inspection it really isn't.
You might say the part before the boolean AND is just a precedence issue — but if it were purely about precedence, the result would be:
$a = (100 && $b) = 200
In reality, though, the higher-precedence && yields to the lower-precedence =, letting $b = 200 bind first.
The reason is that PHP does not strictly follow the precedence definitions, as the PHP manual itself notes:
Note: Although = has a lower precedence than most other operators, PHP will still allow expressions similar to the following: if (!$a = foo()), in which case the return value of foo() is put into $a.
I won't pass judgement on such a design. In C, at any rate, a similar statement is a syntax error. PHP's choice here is very likely for historical reasons.
The curious will want to know exactly why. A reader, jayeeliu, asked about this before too:
Hello laruence:
I have a question about PHP operator precedence.
$t == 1 && $tt = 2
According to PHP's operator precedence this should execute as
(($t == 1) && $tt) = 2
but in practice it should be
($t == 1) && ($tt = 2)
I don't quite understand this.
Actually it's simple. Operator precedence is a means of choosing between reduction rules when the grammar is ambiguous. But in PHP's grammar definition, there is no reduction conflict between the assignment operator and T_BOOLEAN_AND (&&) in the first place:
expr_without_variable:
// There's an implicit rule here, effectively making T_BOOLEAN_AND a "unary operator".
| expr T_BOOLEAN_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr
Finally, by the way: alongside T_BOOLEAN_AND, PHP also defines T_LOGICAL_AND (and) and T_LOGICAL_OR (or). Both of these have lower precedence than assignment, which is where the classic line from so many PHP beginner tutorials comes from:
$result = mysql_query(*) or die(mysql_error());
Similarly, or can be used to emulate the ternary operator (?:):
$person = $who or $person = "laruence"; //equivalent to: $person = empty($who)? "laruence" : $who;
Be First to Comment