为什么可以从字符串变量实例化一个类,而不是PHP中的字符串?

sam*_*rap 10 php

PHP如何工作:

$myClass = 'App\MyClass';
$object = new $myClass;
Run Code Online (Sandbox Code Playgroud)

但这会导致错误:

$myClass = 'MyClass';
$object = new 'App\\'.$myClass;
Run Code Online (Sandbox Code Playgroud)

在第二个例子中,unexpected T_CONSTANT_ENCAPSED_STRING抛出了一个.

事实证明,上面的例子是由于运算符优先级,因为new它具有最高优先级,但......

同样,我可以尝试使用一个字符串进行实例化,如:

$object = new 'App\MyClass';
Run Code Online (Sandbox Code Playgroud)

并抛出同样的错误.为什么是这样?

mar*_*rio 3

PHP 语法在zend_language_parser.y中定义,并且它根本没有为运算符定义任何更复杂的表达式new:

new_expr:
    T_NEW class_name_reference ctor_arguments
            { $$ = zend_ast_create(ZEND_AST_NEW, $2,  }
    |   T_NEW anonymous_class
            { $$ = $2; }
Run Code Online (Sandbox Code Playgroud)

哪里class_name_reference:

class_name_reference:
        class_name      { $$ = $1; }
    |   new_variable    { $$ = $1; }
Run Code Online (Sandbox Code Playgroud)

并new_variable允许一组有限的变量表达式:

new_variable:
        simple_variable
            { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
    |   new_variable '[' optional_expr ']'
            { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
    |   new_variable '{' expr '}'
            { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
    |   new_variable T_OBJECT_OPERATOR property_name
            { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); }
    |   class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
            { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
    |   new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable
            { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
// Copyright (c) 1998-2015 Zend Technologies Ltd., the Zend license 2.00
Run Code Online (Sandbox Code Playgroud)

这就是为什么那里不能有字符串表达式的原因。(它从未被扩展,因为简单的实例化和 $classvarnames 通常就足够了。所以允许的语法与 PHP3 引入时基本相同。)