首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

深度解析:為何應棄用 include_once 與 require_once,改用 include 與 require

     編輯:PHP 相關知識

前言:不只是效能的考量

許多 PHP 開發者知道 include_once 需要檢查已載入檔案列表,因此效能略遜於 include。但這只是冰山一角。本文將深入 PHP 核心原始碼與 APC 快取機制,揭示 include_once 在現代生產環境中隱藏的嚴重缺陷,並論證為何應堅持使用 include / require 搭配良好的架構設計。

一、include_once 的核心執行流程

當 PHP 遇到 include_once("2.php") 時,內部執行邏輯如下:

  1. 嘗試解析絕對路徑:若為相對路徑,需結合 getcwd() 與 include_path 解析真實路徑(opened_path)。
  2. 檢查 EG(included_files):若解析成功,查找全域已載入檔案哈希表。存在則直接返回,不再重複編譯。
  3. 開啟檔案獲取 opened_path:若步驟 1 解析失敗(常見於相對路徑),PHP 必須先 open() 檔案才能取得真實路徑。
  4. 二次檢查 EG(included_files):拿到 opened_path 後再次查找,未存在則進入編譯階段。
  5. 編譯執行:呼叫 compile_file 編譯 opcode。

關鍵痛點:即便檔案已被載入,PHP 在 compile_file 前仍可能產生一次額外的 open() 系統呼叫(步驟 3)。

二、APC 快取機制下的「雙重懲罰」

APC (Alternative PHP Cache) 透過劫持 compile_file 避免重複編譯與檔案讀取。然而 include_once 的邏輯導致:

include_once -> open() 系統呼叫 -> APC 劫持 compile_file -> 從快取返回 opcode

這意味著 每次 include_once 都會產生一次多餘的檔案系統 I/O,抵消了 Opcode 快取「避免 open」的核心優勢。

三、APC 的妥協方案:include_once_override 及其缺陷

為解決此問題,APC 引入 apc.include_once_override=1 設定:

  • 劫持 ZEND_INCLUDE_OR_EVAL opcode handler。
  • 使用 stat() 解析絕對路徑。
  • 若檔案未載入,將 opcode 改寫為 include 執行。

然而,此機制實作極其複雜且充滿邊界 Bug。 經典失效案例:

<?php
set_include_path("/tmp");
function a($arg = array()) {
    include_once("b.php");
}
a();
a();
?>

若 b.php 定義 class B {},啟用 include_once_override 時,第二次呼叫 a() 會拋出 Fatal error: Cannot redeclare class。原因在於 opcode 改寫邏輯在動態 include_path、函式作用域、預設參數等場景下判斷失誤,導致重複編譯。

四、架構層面的反思:為何你需要 *_once?

使用 include_once 往往暴露了架構設計的缺失:

  • 檔案載入順序不可控:依賴執行流決定載入時機,而非明確的依賴圖譜。
  • 缺乏自動載入機制:現代框架(Composer PSR-4、Laravel、Symfony)皆透過 spl_autoload_register 實現「用到才載、精確載入一次」。
  • 全域命名空間汙染:隨意 include 導致符號衝突風險。

最佳實踐:

  1. 全專案採用 Composer 自動載入,拒絕手動 include/require。
  2. 若必須手動載入(如舊專案遷移),統一使用 require(檔案不存在視為嚴重錯誤,立即中止),並在架構層面保證單一入口、單一載入。
  3. 建立明確的模組依賴關係,而非依賴執行時檢查。

結語

include_once / require_once 看似提供了「安全網」,實則在效能(額外 I/O)、穩定性(APC override Bug)、架構(掩蓋設計缺陷)三個維度皆為負資產。棄用它們,擁抱自動載入與嚴謹的模組化設計,才是專業 PHP 工程師的正確選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved