本文由Younes Rafie進行了同行評審。感謝SitePoint所有的同行評審員製作SitePoint內容的最佳狀態!
鑰匙要點
解釋
$code = <<<'code' <span><span><?php </span></span><span><span>$a = 1; </span></span><span>code<span>; </span></span><span> </span><span><span>$tokens = token_get_all($code); </span></span><span> </span><span><span>foreach ($tokens as $token) { </span></span><span> <span>if (is_array($token)) { </span></span><span> <span>echo "Line <span><span>{$token[2]}</span>: "</span>, token_name($token[0]), " ('<span><span>{$token[1]}</span>')"</span>, PHP_EOL; </span></span><span> <span>} else { </span></span><span> <span>var_dump($token); </span></span><span> <span>} </span></span><span><span>} </span></span>
>從上述輸出中有幾個值得注意的點。第一個點是,並非所有源代碼的所有部分都命名為令牌。相反,某些符號本身被視為令牌(例如=,;,:,?等)。第二點是,Lexer實際上做的不只是簡單地輸出一個令牌流。在大多數情況下,它也存儲了lexeme(由令牌匹配的值)和匹配令牌的行號(用於堆棧跟踪之類的內容)。
階段2 - 解析>生成的解析器階段將令牌流從Lexer作為輸入中獲取,並有兩個作業。首先,它通過嘗試將其與BNF語法文件中定義的任何語法規則相匹配,從而驗證令牌順序的有效性。這樣可以確保令牌流中的代幣形成有效的語言構造。解析器的第二個作業是生成
抽象語法樹(AST) - 下一階段將使用的源代碼的樹視圖(彙編)。
我們可以使用php-ast擴展名來查看
Line 1: T_OPEN_TAG ('<?php ') Line 2: T_VARIABLE ('$a') Line 2: T_WHITESPACE (' ') string(1) "=" Line 2: T_WHITESPACE (' ') Line 2: T_LNUMBER ('1') string(1) ";"
$code = <<<'code' <span><span><?php </span></span><span><span>$a = 1; </span></span><span>code<span>; </span></span><span> </span><span><span>print_r(ast<span>\parse_code</span>($code, 30)); </span></span>
>標誌 - 一個指定過載行為的整數(例如,ASTAST_BINARD_OP節點將具有區分發生哪些二進制操作的標誌)
Lineno彙編階段消耗了AST,它通過遞歸穿越樹來發出opcods。這個階段還進行了一些優化。這些包括通過字面論據(例如strlen(“ ABC”)到int(3))和折疊持續的數學表達式(例如60 * 60 * 24 to int(86400))。
>我們可以在此階段以多種方式檢查OpCode輸出,包括OPCACHE,VLD和PHPDBG。我將使用VLD為此,因為我覺得輸出更友好。>讓我們看看以下file.php腳本的輸出是什麼:
執行以下命令:
$code = <<<'code' <span><span><?php </span></span><span><span>$a = 1; </span></span><span>code<span>; </span></span><span> </span><span><span>$tokens = token_get_all($code); </span></span><span> </span><span><span>foreach ($tokens as $token) { </span></span><span> <span>if (is_array($token)) { </span></span><span> <span>echo "Line <span><span>{$token[2]}</span>: "</span>, token_name($token[0]), " ('<span><span>{$token[1]}</span>')"</span>, PHP_EOL; </span></span><span> <span>} else { </span></span><span> <span>var_dump($token); </span></span><span> <span>} </span></span><span><span>} </span></span>
我們的輸出是:
Line 1: T_OPEN_TAG ('<?php ') Line 2: T_VARIABLE ('$a') Line 2: T_WHITESPACE (' ') string(1) "=" Line 2: T_WHITESPACE (' ') Line 2: T_LNUMBER ('1') string(1) ";"
> Opcodes類似於原始源代碼,足以與基本操作一起進行。 (我不會深入研究本文中的opcodes的詳細信息,因為這本身將需要幾個整個文章。)在上面腳本中沒有在OpCode級別上應用優化,但是正如我們所看到的,編譯階段通過解決恆定條件(php_version ==='7.1.0-dev')來做出一些。
$code = <<<'code' <span><span><?php </span></span><span><span>$a = 1; </span></span><span>code<span>; </span></span><span> </span><span><span>print_r(ast<span>\parse_code</span>($code, 30)); </span></span>
>
>命令:
>輸出:
ast\Node Object ( [kind] => 132 [flags] => 0 [lineno] => 1 [children] => Array ( [0] => ast\Node Object ( [kind] => 517 [flags] => 0 [lineno] => 2 [children] => Array ( [var] => ast\Node Object ( [kind] => 256 [flags] => 0 [lineno] => 2 [children] => Array ( [name] => a ) ) [expr] => 1 ) ) ) )
>我們可以看到恆定條件已被刪除,並且兩個迴聲指令已被壓縮到單個指令中。這些只是對Opcache在腳本的Opcodes上進行的許多優化的味道。不過,我不會瀏覽本文的各種優化級別,因為這本身也是一篇文章。
>階段4 - 解釋<span>if (PHP_VERSION === '7.1.0-dev') { </span> <span>echo 'Yay', PHP_EOL; </span><span>} </span>
>最後階段是對opcodes的解釋。這是Opcodes在Zend Engine(ZE)VM上運行的地方。對於這個階段,實際上幾乎沒有什麼可說的(至少從高級角度來看)。輸出幾乎是您通過echo,print,var_dump等命令輸出輸出的任何內容。
>因此,這是一個有趣的事實,而不是在此階段挖掘任何復雜的事實:PHP在生成自己的VM時需要自己作為依賴性。這是因為VM是由PHP腳本生成的,因為它更簡單並且更易於維護。>我們已經簡要介紹了PHP解釋器在運行PHP代碼時通過的四個階段。這涉及使用各種擴展(包括令牌,PHP-ast,opcache和vld)來操縱和查看每個階段的輸出。
。>我希望本文能夠幫助您對PHP的解釋器有更好的整體理解,並顯示了Opcache擴展的重要性(用於其緩存和優化能力)。
經常詢問有關PHP執行過程的問題(常見問題解答)>
PHP在執行過程中如何處理錯誤?php擴展是在PHP語言中添加新功能和功能的模塊。在執行過程中,它們被加載到PHP運行時環境中,可用於執行從數據庫訪問到圖像處理的廣泛任務。 PHP擴展名為C編寫,並編譯為機器代碼,這使其非常快速有效。它們是PHP生態系統的關鍵組成部分,並有助於其靈活性和功率。
>>
PHP在執行過程中如何處理內存管理? PHP具有內置內存管理器,可以在執行過程中處理內存分配和Deallocation。內存管理器根據需要為變量和數據結構分配內存,並在不再需要內存時對內存進行交易。 PHP還具有一個垃圾收集器,該垃圾收集器會自動釋放不再使用的內存。這有助於防止內存洩漏並將內存使用控制在控制之下。 > Web服務器在PHP執行過程中的作用是什麼?>
> Web服務器在PHP執行中起關鍵作用過程。它負責處理HTTP請求,對這些請求運行PHP腳本,然後將HTTP響應發送回客戶端。 Web服務器與PHP解釋器和PHP引擎緊密合作,以執行PHP腳本並生成動態網頁。 PHP最常用的Web服務器是Apache和Nginx。 MySQL,PostgreSQL和SQLite。它在執行過程中使用數據庫特異性擴展與這些數據庫進行交互。這些擴展提供了一組功能,可用於連接到數據庫,執行SQL查詢,獲取結果並處理錯誤。 PHP還支持PDO(PHP數據對象)擴展名,該擴展提供了數據庫交互的數據庫-Nostic接口。PHP對會話管理具有內置支持,這使其可以在不同的HTTP請求之間維護狀態。啟動會話後,PHP會創建唯一的會話ID,並將其存儲在客戶端瀏覽器上的cookie中。然後,此會話ID通過每個後續請求發送回服務器,允許PHP識別客戶端並檢索相應的會話數據。 PHP的會話管理功能使在Web應用程序中實現用戶身份驗證,購物車和其他狀態功能變得易於實現。
以上是PHP如何執行 - 從源代碼到渲染的詳細內容。更多資訊請關注PHP中文網其他相關文章!