Неожиданное поведение при назначении нескольких переменных в блоке if ()

В духе оценки коротких замыканий, таких как «и» Python, и при сохранении результатов проверок я решил посмотреть, как это можно было бы лучше всего решить на PHP, но у меня возникла проблема.

неожиданный

<?php function check_a() { return 'A'; } function check_b() { return 'B'; } function check_c() { return 'C'; } if($a = check_a() && $b = check_b() && $c = check_c()) { var_dump($a); var_dump($b); var_dump($c); } 

Результаты в:

 bool(true) bool(true) string(1) "C" 

код для того, что я хотел произойти

 <?php function check_a() { return 'A'; } function check_b() { return 'B'; } function check_c() { return 'C'; } // if(($a = check_a()) && ($b = check_b()) && $c = check_c()) // equivalent to line below if(($a = check_a()) && ($b = check_b()) && ($c = check_c())) { var_dump($a); var_dump($b); var_dump($c); } 

Результаты в:

 string(1) "A" string(1) "B" string(1) "C" 

Почему неожиданный пример действует таким образом?

Это вопрос приоритетности оператора . Выражение присваивания возвращает назначенное значение , поэтому вы ожидаете получить A и B для первых двух операций. Причина, по которой вы получаете логическое значение true заключается в том, что оператор && имеет более высокий приоритет, чем оператор присваивания, поэтому в исходном выражении

 $a = check_a() && $b = check_b() && $c = check_c() 

$a получает значение check_a() && $b = check_b() && $c = check_c() ,

$b получает значение check_b() && $c = check_c() ,

и $c получает значение check_c() .

Выражения check_a() && $b = check_b() && $c = check_c() и check_b() && $c = check_c() возвращают логическое значение true , так как использование оператора && вызывает выражение, которое должно быть оценено как booleans , и все компоненты выражений, соединенных с помощью && оцениваются как true .

Чтобы получить ожидаемые результаты, вы можете добавлять скобки так же, как и вы, или использовать вместо логического оператора вместо && , потому что он имеет более низкий приоритет, чем оператор присваивания.

 if($a = check_a() and $b = check_b() and $c = check_c()) { 

Результат boolean && – это bool! && связывает сильнее = . Поэтому $b присваивается ('B' && $c) что является bool … То же, очевидно, с $a