簡體   English   中英

為什么可以從字符串變量實例化一個類,而不是PHP中的字符串?

[英]Why can you instantiate a class from a string variable but not a string in PHP?

PHP如何工作:

$myClass = 'App\MyClass';
$object = new $myClass;

但這會導致錯誤:

$myClass = 'MyClass';
$object = new 'App\\'.$myClass;

在第二個示例中,拋出了unexpected T_CONSTANT_ENCAPSED_STRING

事實證明,上面的例子是由於運算符優先級,因為new優先級最高,但......

同樣,我可以嘗試使用一個字符串進行實例化,如:

$object = new 'App\MyClass';

並拋出同樣的錯誤。 為什么是這樣?

解析器的實現不是通用的,因此在某些情況下,解析器會打擾引擎實際上可以處理的事情。 那里(仍然)甚至不是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_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM