介紹
公司主營業(yè)務(wù):成都做網(wǎng)站、成都網(wǎng)站制作、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。成都創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。成都創(chuàng)新互聯(lián)公司推出安達(dá)免費(fèi)做網(wǎng)站回饋大家。
目前禁止從__toString()拋出異常,并將導(dǎo)致致命錯(cuò)誤。這就使得調(diào)用任意代碼變得很危險(xiǎn),并使其成為一個(gè)有問題的通用API。此RFC旨在取消此限制。
當(dāng)前行為的基本原理是,在整個(gè)引擎和標(biāo)準(zhǔn)庫的許多地方都執(zhí)行了字符串轉(zhuǎn)換,并不是所有地方都準(zhǔn)備“正確地”處理異常,即盡可能早地處理異常。
從技術(shù)角度來看,這種限制最終是無效的,因?yàn)樽址D(zhuǎn)換期間的異常仍然可以由將可恢復(fù)錯(cuò)誤轉(zhuǎn)換為異常的錯(cuò)誤處理程序觸發(fā):
set_error_handler(function() { throw new Exception(); }); try { (string) new stdClass; } catch (Exception $e) { echo "(string) threw an exception...\n"; }
事實(shí)上,Symfony利用這個(gè)漏洞來繞過當(dāng)前的限制。不幸的是,這依賴于$errcontext參數(shù),它在PHP 8中消失了.
盡管如此,在我們對該代碼庫中的字符串轉(zhuǎn)換進(jìn)行了全面審核之前,過去關(guān)于該主題的討論一直沒有放松這種限制。這已在附加的實(shí)現(xiàn)請求中完成。
建議
允許從__toString()拋出異常,它的行為與往常一樣。不再觸發(fā)致命錯(cuò)誤。
另外,將“不能轉(zhuǎn)換為字符串”和“__toString()必須返回一個(gè)字符串值”可恢復(fù)的致命錯(cuò)誤轉(zhuǎn)換為正確的錯(cuò)誤異常,這與PHP 7中建立的錯(cuò)誤策略一致。
擴(kuò)展準(zhǔn)則
想要優(yōu)雅地處理來自字符串轉(zhuǎn)換的異常的擴(kuò)展作者,應(yīng)該考慮以下準(zhǔn)則:
● 如果zval_get_string()、convert_to_string()和friends生成一個(gè)異常,它們?nèi)匀粫梢粋€(gè)字符串。這個(gè)字符串被保證是暫存的。這意味著沒有必要釋放它,但可以這樣做。在上下文中,您可以選擇更方便的選項(xiàng)。
● 如果從對象到字符串的轉(zhuǎn)換失敗,則字符串轉(zhuǎn)換的結(jié)果將為空字符串,如果將數(shù)組轉(zhuǎn)換為字符串,并且錯(cuò)誤處理程序?qū)⒔Y(jié)果通知提升為異常,則為“Array”。(這種行為和以前一樣。)
● 通常情況下,使用通常的if (EG(exception))檢查來檢查是否拋出了異常就足夠了:
zend_string *str = zval_get_string(val); if (EG(exception)) { // Possibly free other resources here. return; }
除此之外,還提供了一些幫助api,將轉(zhuǎn)換建模為容易出錯(cuò)的操作:
// Like zval_get_string() but returns NULL on conversion failure. zend_string *str = zval_try_get_string(val); if (!str) { // Possibly free other resources here. return; } // Main code. zend_string_release(str); // Like zval_get_tmp_string() but returns NULL on conversion failure. zend_string *tmp, *str = zval_try_get_tmp_string(val, &tmp); if (!str) { // Possibly free other resources here. return; } // Main code. zend_tmp_string_release(tmp); // Like convert_to_string() but returns a boolean indicating conversion success/failure. if (!try_convert_to_string(val)) { // Possibly free other resources here. return; } // Main code.
如果轉(zhuǎn)換失敗,try_convert_to_string()將不會修改原始值。因此,使用它比使用convert_to_string()和異常檢查更安全。
雖然檢查每一個(gè)字符串轉(zhuǎn)換肯定會使您處于安全的一方,但忽略這些檢查通常只會導(dǎo)致一些不必要的計(jì)算和可能的冗余警告。您應(yīng)該注意的主要事情是修改持久結(jié)構(gòu)(如數(shù)據(jù)庫)的操作。
不向后兼容的變更
從可恢復(fù)的致命錯(cuò)誤到錯(cuò)誤異常的轉(zhuǎn)換在技術(shù)上是BC中斷的。
以上就是PHP 7.4允許從 __toString() 拋出異常的詳細(xì)內(nèi)容,更多請關(guān)注創(chuàng)新互聯(lián)其它相關(guān)文章!