[問題]
儘管有程式設計經驗,但新手PHP中的屬性預設錯誤令我困惑。代碼:
class Foo {
public $path = array(
realpath(".")
);
}
產生文法錯誤。但是,以下內容可以無縫運行:
$path = array(
realpath(".")
);
問題出現了:為什麼不能在屬性預設值中呼叫函數?這是故意的還是實現中的缺陷?
[答案]
PHP 編譯器程式碼顯示此限制是故意的,儘管沒有官方的理由。可靠地實現此功能會帶來一定的挑戰,PHP 目前實現的限制就證明了這一點。
編譯器的語法將類別變數宣告定義為:
class_variable_declaration: //... | T_VARIABLE '=' static_scalar //... ;
因此,要指派像 $path 這樣的變數值,預期值必須與靜態標量對齊。這包括其值也是靜態標量的陣列:
static_scalar: /* compile-time evaluated scalars */ //... | T_ARRAY '(' static_array_pair_list ')' // ... //... ;
如果語法允許使用以下與程式碼範例一致的語法,則腳本將遇到「無效的綁定類型」錯誤:
class_variable_declaration: //... | T_VARIABLE '=' T_ARRAY '(' array_pair_list ')' // ... ;
解析給定的程式碼範例顯示以下步驟:
zend_do_begin_class_declaration() // Adds an opcode array_init(), zend_do_add_static_array_element() // Do not create new opcodes, add array to class properties zend_do_declare_property() // Declares the property zend_do_early_binding() // Consumes the last opcode and evaluates it
如果操作碼不是預期的(例如,與函數或方法相關),則會拋出錯誤。
允許非靜態陣列產生一個 INIT_ARRAY 操作碼,它會破壞 zend_do_early_binding():
DECLARE_CLASS 'Foo' SEND_VAL '.' DO_FCALL 'realpath' INIT_ARRAY
為了適應屬性預設值中的函數調用,需要一個作用域為類別變數聲明的新操作碼數組,類似於方法定義。然而,確定此類評估的時機提出了額外的挑戰。
其他動態語言已經設法解決了這個問題,但它仍然是 PHP 中缺少的功能,可能是由於其複雜性和感知的低優先級。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3