PHP如何執行 - 從源代碼到渲染
本文由Younes Rafie進行了同行評審。感謝SitePoint所有的同行評審員製作SitePoint內容的最佳狀態!
>受Ruby代碼如何執行的最新文章的啟發,本文涵蓋了PHP代碼的執行過程。
鑰匙要點
PHP代碼的執行涉及四個階段:Lexing,解析,編譯和解釋。每個階段在將PHP源代碼轉換為機器可讀代碼的過程中至關重要。
> Lexing或令牌化是將字符串(PHP源代碼)變成一個令牌序列的過程。每個令牌是其匹配值的命名標識符。此階段還存儲lexeme和匹配令牌的行號。- 驗證令牌順序的有效性,並生成抽象語法樹(AST)。 AST是在編譯階段使用的源代碼的樹視圖。
- 解釋階段是在Zend Engine(ZE)VM上運行Opcodes的最後階段。此階段的輸出是您的PHP腳本通過echo,print,var_dump等命令輸出的內容。 >
- 簡介
- >當我們執行PHP代碼時,引擎蓋下發生了很多事情。從廣義上講,執行代碼時,PHP解釋器將經歷四個階段:
- Lexing
- 解析
彙編
解釋
- >本文將瀏覽這些階段,並展示我們如何查看每個階段的輸出,以真正查看發生了什麼。請注意,雖然某些使用的擴展程序應該已經是您的PHP安裝的一部分(例如Tokenizer和opcache),但需要手動安裝和啟用其他擴展程序(例如,PHP-ast和VLD)。 階段1 - Lexing
- Lexing(或令牌化)是將字符串(在這種情況下為PHP源代碼)轉換為令牌序列的過程。令牌只是其匹配的值的命名標識符。 PHP使用re2c從zend_language_scanner.l定義文件。 >我們可以通過令牌擴展名看到Lexing階段的輸出:
- >輸出:
$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 - 解析也生成了解析器,這次是通過BNF語法文件與野牛一起生成的。 PHP使用LALR(1)(向前,從左到右)無上下文語法。前面的外觀僅意味著解析器能夠在解析時可能會遇到的歧義。從左到右的部分意味著它從左到右解析令牌流。
>>生成的解析器階段將令牌流從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- lineno - 線號,從較早的令牌信息中可以看出
- 兒童 - 子節點,通常會進一步分解該節點的一部分(例如,功能節點將具有孩子:參數,返回類型,身體等)
- >此階段的AST輸出很方便用於諸如靜態代碼分析儀(例如phan)之類的工具。
階段3 - 彙編
彙編階段消耗了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) ";"
登入後複製登入後複製> OPCACHE不僅可以簡單地緩存OPCODE(因此繞過Lexing,解析和編譯階段)。它還包含許多不同級別的優化。讓我們將優化級別提高到四個傳球,以查看出來的內容:$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的命令行接口和Web服務器接口之間有什麼區別? -line接口(CLI)和Web服務器接口是運行PHP腳本的兩種不同方法。 CLI用於從命令行運行PHP腳本,而Web服務器接口則用於響應Web請求來運行PHP腳本。兩個接口之間的主要區別是它們處理輸入和輸出的方式。在CLI中,從命令行讀取輸入,並將輸出寫入控制台。在Web服務器接口中,從HTTP請求讀取輸入,並將輸出寫入HTTP響應。>
PHP在執行過程中如何處理錯誤?php具有強大的錯誤處理。允許其在執行過程中處理錯誤的機制。發生錯誤時,PHP會生成錯誤消息並將其發送到錯誤處理程序。錯誤處理程序可以根據錯誤報告設置顯示錯誤消息,將其記錄或忽略。 PHP還支持異常處理,這使其可以以更結構化和易於管理的方式處理錯誤。 > > php擴展在執行過程中的作用是什麼?
php擴展是在PHP語言中添加新功能和功能的模塊。在執行過程中,它們被加載到PHP運行時環境中,可用於執行從數據庫訪問到圖像處理的廣泛任務。 PHP擴展名為C編寫,並編譯為機器代碼,這使其非常快速有效。它們是PHP生態系統的關鍵組成部分,並有助於其靈活性和功率。
>> PHP如何優化執行過程?
PHP使用多種技術來優化執行過程。這些技術之一是OpCode緩存,其中涉及將PHP引擎生成的字節碼存儲在內存中,以便可以在後續執行中重複使用。這消除了每次執行PHP腳本的必要性,從而大大提高了性能。 PHP還使用Just-In-time(JIT)彙編,其中涉及在運行時將字節碼編譯到機器代碼中以進一步提高性能。>
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在執行過程中如何處理會話管理?
PHP對會話管理具有內置支持,這使其可以在不同的HTTP請求之間維護狀態。啟動會話後,PHP會創建唯一的會話ID,並將其存儲在客戶端瀏覽器上的cookie中。然後,此會話ID通過每個後續請求發送回服務器,允許PHP識別客戶端並檢索相應的會話數據。 PHP的會話管理功能使在Web應用程序中實現用戶身份驗證,購物車和其他狀態功能變得易於實現。
以上是PHP如何執行 - 從源代碼到渲染的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

PHP8.1中的枚舉功能通過定義命名常量增強了代碼的清晰度和類型安全性。 1)枚舉可以是整數、字符串或對象,提高了代碼可讀性和類型安全性。 2)枚舉基於類,支持面向對象特性,如遍歷和反射。 3)枚舉可用於比較和賦值,確保類型安全。 4)枚舉支持添加方法,實現複雜邏輯。 5)嚴格類型檢查和錯誤處理可避免常見錯誤。 6)枚舉減少魔法值,提升可維護性,但需注意性能優化。

會話劫持可以通過以下步驟實現:1.獲取會話ID,2.使用會話ID,3.保持會話活躍。在PHP中防範會話劫持的方法包括:1.使用session_regenerate_id()函數重新生成會話ID,2.通過數據庫存儲會話數據,3.確保所有會話數據通過HTTPS傳輸。

SOLID原則在PHP開發中的應用包括:1.單一職責原則(SRP):每個類只負責一個功能。 2.開閉原則(OCP):通過擴展而非修改實現變化。 3.里氏替換原則(LSP):子類可替換基類而不影響程序正確性。 4.接口隔離原則(ISP):使用細粒度接口避免依賴不使用的方法。 5.依賴倒置原則(DIP):高低層次模塊都依賴於抽象,通過依賴注入實現。

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

RESTAPI設計原則包括資源定義、URI設計、HTTP方法使用、狀態碼使用、版本控制和HATEOAS。 1.資源應使用名詞表示並保持層次結構。 2.HTTP方法應符合其語義,如GET用於獲取資源。 3.狀態碼應正確使用,如404表示資源不存在。 4.版本控制可通過URI或頭部實現。 5.HATEOAS通過響應中的鏈接引導客戶端操作。

在PHP中,異常處理通過try,catch,finally,和throw關鍵字實現。 1)try塊包圍可能拋出異常的代碼;2)catch塊處理異常;3)finally塊確保代碼始終執行;4)throw用於手動拋出異常。這些機制幫助提升代碼的健壯性和可維護性。

匿名類在PHP中的主要作用是創建一次性使用的對象。 1.匿名類允許在代碼中直接定義沒有名字的類,適用於臨時需求。 2.它們可以繼承類或實現接口,增加靈活性。 3.使用時需注意性能和代碼可讀性,避免重複定義相同的匿名類。
