[英]Why can you instantiate a class from a string variable but not a string in PHP?
解析器的实现不是通用的,因此在某些情况下,解析器会打扰引擎实际上可以处理的事情。 那里(仍然)甚至不是PHP的官方正式语法,这使得很难预测这样的事情,而不是简单地尝试它们。 这是PHP世界的方式:)
PHP期望对象定义的变量或名称引用,它只是不允许字符串。 你可以使用这个基于''空字符串命名变量的hack立即根据${false}
计算到${''}
的事实创建和使用,如下所示从字符串创建一个对象:
$obj = new ${!${''} = 'App\MyClass'}();
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; }
class_name_reference:
class_name { $$ = $1; }
| new_variable { $$ = $1; }
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
这就是为什么你不能在那里有字符串表达式。 (它从未被扩展,因为普通的实例化和$ classvarnames通常就足够了。因此,当引入它时,允许的语法与PHP3中的大致相同。)
这是因为运算符优先级: http : //php.net/manual/en/language.operators.precedence.php
因为'new'的优先级高于''。 它首先被处理。
就你的代码而言,编译器看到的是:
$myClass = 'MyClass';
$object = new 'App\\';
$object = $object . $myClass;
对于问题的第二部分,为什么: $object = new 'App\\MyClass'
; 不起作用。 我不确定。
如果我不得不猜测我会说这是因为当你执行new 'App\\MyClass'
,解析器在遇到它时不知道它是一个字符串。 直到该行已被处理,它不知道它是否处理字符串,数字,对象等。它可以发现并正确地将其转换为字符串,但我猜这会回到运算符优先级,它不会在处理'new'运算符之前,执行这些类型的强制转换。
奇怪的是,我刚刚在Quercus PHP中测试它并运行良好。 正如其他人提到的那样,php并不是一种完全定义的语言,所以像这样的东西表现为实现之间的差异。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.