"未定义的变量"在if子句中赋值后使用

时间:2014-08-11 08:52:43

标签: php variables expression conditional-statements

if (true && 1 == $x = 1 && $x) { echo "Hello world!"; }

我收到$ x的未定义变量通知。解析器此时不应该知道$ x,因为它从左到右解决了If-Clause?

1 个答案:

答案 0 :(得分:1)

观察到的行为是由于解析表达式的方式。以下

if (1 == $x = 1 && $x) {
    echo "Hello world!";
}

产生“Undefined variable:x”并且回显,但是

if (1 == ($x = 1) && $x) {
    echo "Hello world!";
}

“正常”并按预期发出 Hello world!

这是因为前者相当于

if (1 == ($x = (1 && $x))) {
    echo "Hello world!";
}

并且$ x的使用 将用于赋值的表达式。由于在赋值生效之前对它进行了求值,因此根据PHP,$ x仍然是一个“未定义的变量”。

解决方案:

  • 如图所示使用括号;或者,
  • 我建议在条件表达式中避免变量赋值。

虽然operator precedence是主要的替罪羊,但第一种形式是而不是等同于(1 == $x) = (1 && $x),这是直接跟随优先表时的推导。如果以这种方式解析它会导致“语法错误,=意外”。

这种解析是PHP的一个怪癖,与C语法规则不同。 (可以在zend_language_parser.y中找到PHP的YACC规则。)

  • PHP:1 && $x = 2 - > 1 && ($x = 2),按照上述等效性。即使&&声称具有更高的优先级,也会发生这种情况。

  • C:1 && x = 2 - > (1 && x) = 2,语法无效:“左值作为赋值的左操作数”。在C中,&&运算符在表达式中确实具有更高的优先级。

&&替换为==时,同样的行为很明显:尽管分配的文档优先级较低,但当赋值是表达式的一部分时,简单优先级表会产生误导和不准确。

总之, $x = expr作为表达式的一部分被等效地解析为($x = (expr)) ,其中expr本身就是一个复杂的包含运算符和其他表达式的表达式。