PHP 5.5中的半复杂解引用

时间:2014-06-27 10:23:26

标签: php php-5.5

一般的想法是这样的:

  • 我有一个班级test
  • 该类具有公共静态属性$commands
  • test::$commandskey => Callback
  • 的数组
  • 我在[{1}}
  • 中保存了一个密钥

所有这些都考虑过了,我应该写下这个:

$cmdkey

然而,这样做会产生:

  

PHP注意:未定义的变量:$命令
  PHP致命错误:函数名称必须是字符串

我这样解决了这个问题:

self::$commands[$cmdkey]($argument);

在解除引用之前,这是一种反吹,但在PHP中却是......

我是否疯了,或者我确实在PHP解析器中发现了一个错误?

1 个答案:

答案 0 :(得分:3)

看起来像是

test::$commands[$cmdkey](foo)

被解释为

test::($commands[$cmdkey])(foo)

即。首先获取$commands[$cmdkey]包含的内容,并将其用作test中的函数名称。请注意,只有test::$commands[$cmdkey]正常绑定。

考虑:

class test {
    public static $commands = array('x' => 'strlen');

    public static function other() {
        print 'here!';
    }
}

$cmdkey = 'x';

$commands = array('x' => 'other'); // *

print test::$commands[$cmdkey]('abc');

如果您注释掉*行,您将获得

Notice: Undefined variable: commands...
Fatal error: Function name must be a string...

可悲的是,http://www.php.net/manual/en/language.operators.precedence.php缺少::所以很难说这种行为是否有意,但这绝对是违反直觉的。

这是PHPParser所说的:

$code = <<<'EOF'
<?php test::$commands[123](456); ?>
EOF;

$parser = new PhpParser\Parser(new PhpParser\Lexer);
$stmts = $parser->parse($code);
$nodeDumper = new PhpParser\NodeDumper;
print $nodeDumper->dump($stmts);

结果:

0: Expr_StaticCall(
    class: Name(
        parts: array(
            0: test
        )
    )
    name: Expr_ArrayDimFetch(
        var: Expr_Variable(
            name: commands
        )
        dim: Scalar_LNumber(
            value: 123
        )
    )
    args: array(
        0: Arg(
            value: Scalar_LNumber(
                value: 456
            )
            byRef: false
            unpack: false
        )
    )
)