How does variable assignment in an expression work

2020-04-08 14:10发布

问题:

This is a practice I've seen before, but not very often: A variable is assigned to a value at the same time the value itself is evaluated (or is it the expression itself that is evaluated?). Example:

// Outputs "The value is 1"
$value = 1;
if ($var = $value) {
    echo "The value is $var";
}

Seems to be the same as:

$value = 1;
$var = $value;
if ($var) {
    echo "The value is $var";
}

Another example:

// Outputs "The value is 1"
$value = 1;
echo "The value is ".$var = $value;

I've been using this a little bit to shorten up my code, mainly the first example: for evaluating the first variable or expression while assigning it to another within the same expression. Something like this:

if ($status = User::save($data)) {
    echo "User saved.";
}
// do something else with $status

This seems so basic, but I can't actually find any documentation on this, maybe I'm not sure where to look. I've only recently figured out how this works after seeing it for years, and I really like using it, but I don't want to use it haphazardly.

It makes code shorter, maybe not quite as clear to some, but definitely less repetitive. Are there any caveats with this method? Is this perfectly safe or are there any cases where it might fail or cause unexpected behavior? This doesn't seem to be a very common practice, so I was hoping to find an explanation before I start "going nuts" with it. If it is documented, links to the correct page will be much appreciated.

回答1:

From http://uk3.php.net/manual/en/language.expressions.php:

PHP takes expressions much further, in the same way many other languages do. PHP is an expression-oriented language, in the sense that almost everything is an expression. Consider the example we've already dealt with, $a = 5. It's easy to see that there are two values involved here, the value of the integer constant 5, and the value of $a which is being updated to 5 as well. But the truth is that there's one additional value involved here, and that's the value of the assignment itself. The assignment itself evaluates to the assigned value, in this case 5. In practice, it means that $a = 5, regardless of what it does, is an expression with the value 5. Thus, writing something like $b = ($a = 5) is like writing $a = 5; $b = 5; (a semicolon marks the end of a statement). Since assignments are parsed in a right to left order, you can also write $b = $a = 5.

Many people would argue that you shouldn't use this behaviour very often. For instance, distinguishing between:

if ($a == 5) { ... }

and

if ($a = 5) { ... }

is tricky! The two common idiomatic ways of writing the above to distinguish them:

if (5 == $a) { ... }
if (($a = 5)) { ... }

The first is called a yoda condition and causes a syntax error if a equals character is left out. The latter won't behave any differently when run, but some code checkers will output warnings when the expression doesn't have the extra parentheses.



回答2:

http://php.net/manual/en/language.operators.precedence.php is what you probably need.

PHP expressions being evaluated in turn, in order from highest precedence to lower.
So, first we have assignment evaluated and then apply conditional statement on it. There is also some type juggling magic involved, to convert return value to boolean on the fly

Are there any caveats with this method?

Sure. If zero being a valid return value, your code may fail you. A common example is strpos() function:

if ($pos = strpos("a","aaa"))...


回答3:

The result of an assigment is the result of the right hand expression, so $var = $value evaluates to $value. Now, you have to take into account what exactly means FALSE or TRUE in PHP.

From the documentation:

FALSE:
 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

TRUE:
  everything not listed above

The ifs are hit if the assignment evaluates to TRUE.



回答4:

How does variable assignment in an expression work?

It's obvious, maybe too obvious, so I say it: Always the same. An expression is an expressionDocs.

Let's put it apart:

if ($var = $value)

[1] := if ([2])
[2] := $var = $value
  1. Is an if expression. That is the boolean value of [2].
  2. Is a variable assignment expression. Results in the value of $value.

A common mistake therefore is to write

if ($a = $b)

when it was meant to write

if ($a == $b)

can happen while typing.

In PHP basically "anything that has a value" is an expression.