| 特性 | include() | require() |
| 檔案不存在 | 發出 Warning(警告),腳本繼續執行 | 拋出 Fatal Error(致命錯誤),腳本立即停止 |
| 效能特徵 | 每次執行都讀取、解析、編譯 | 編譯階段即包含檔案內容(類似 C #include) |
| 條件包含 | 支援動態條件判斷 | 無條件包含(編譯期決定) |
| 返回值處理 | 可接收被包含檔案的 return 值 | 同支援 |
| 適用場景 | 模板檔案、條件載入、非核心依賴 | 核心類別、設定檔、必要依賴 |
底層機制原理
include():運行時動態包含
<?php
// 編譯階段:僅生成「執行 include 指令」的 opcode
// 運行階段:遇到 include 才讀取檔案、編譯、執行
if ($condition) {
include 'optional_module.php'; // 條件成立才載入
}
// 迴圈中動態包含不同檔案
foreach ($modules as $module) {
include "modules/{$module}.php"; // 每次迴圈重新編譯
}
關鍵點:PHP 4.3.5 以前,檔案不存在僅發出 Warning 繼續執行;之後版本統一行為。
require():編譯期靜態包含
<?php
// 編譯階段:直接將檔案內容「展開」到當前 opcode 流中
// 相當於將 require 'config.php' 替換為 config.php 完整內容
require 'core/Database.php'; // 必須存在,否則編譯失敗
require 'config/app.php'; // 設定檔缺失無法運行
// 即使在條件判斷中,require 也會被編譯期處理
if (false) {
require 'never_used.php'; // 仍會嘗試包含,檔案不存在報錯
}
效能深度對比
微觀基準測試
<?php
// 測試檔案:simple.php 內容
// include 版本
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
include 'simple.php';
}
echo "include: " . (microtime(true) - $start) . "s\n";
// require 版本
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
require 'simple.php';
}
echo "require: " . (microtime(true) - $start) . "s\n";
/* 典型輸出(PHP 8.0+,OpCache 啟用):
include: 0.012s
require: 0.008s
差異微小,OpCache 將編譯結果快取,運行期差異極小
*/
/* OpCache 關閉時差異明顯:
include: 0.45s (每次重新編譯)
require: 0.12s (編譯期展開,運行期無額外開銷)
*/
效能結論
- OpCache 啟用(生產標配):兩者效能差異可忽略,編譯結果均被快取
- OpCache 關閉(開發環境):
require 顯著快於 include
- 迴圈/高頻呼叫場景:優先
require_once/include_once 避免重複包含
進階變體:_once 系列
| 函數 | 行為 | 使用建議 |
include_once() | 檢查是否已包含,未包含才執行 include | 模板片段、可能重複引入的工具檔 |
require_once() | 檢查是否已包含,未包含才執行 require | 類別定義、介面、Trait、核心設定(最常用) |
<?php
// 類別定義檔:必須用 require_once 防止重複定義錯誤
require_once 'models/User.php';
require_once 'interfaces/RepositoryInterface.php';
require_once 'traits/Loggable.php';
// 設定檔:require_once 確保單一實例
require_once 'config/database.php';
require_once 'config/redis.php';
// 模板片段:include_once 允許條件載入
if ($showSidebar) {
include_once 'templates/sidebar.php';
}
實戰最佳實踐指南
1. 現代 PHP 專案結構(PSR-4 + Composer 自動載入)
<?php
// 入口檔案:僅需引入自動載入器
require_once __DIR__ . '/vendor/autoload.php';
// 其餘類別透過命名空間自動解析,完全不需要手寫 include/require
use App\Models\User;
use App\Services\PaymentService;
$user = new User();
$payment = new PaymentService();
核心原則:應用層代碼零 require/include,全權交給 Composer 自動載入器。
2. 僅在必要時手動包含
- 第三方無 Composer 支援的舊庫
- 動態模板渲染(View 層)
- 條件載入的大型功能模組(Code Splitting)
- 設定檔(環境差異大)
3. 路徑解析最佳實踐
<?php
// 絕對路徑:最安全、效能最好
require_once __DIR__ . '/../config/app.php';
// 相對路徑:依賴 include_path,易出錯
// require_once 'config/app.php'; // 不推薦
// 動態路徑:使用 Dirname 遞歸
$root = dirname(__DIR__, 3); // 向上 3 層
require_once $root . '/shared/kernel.php';
4. 錯誤處理模式
<?php
// 核心依賴:require 失敗即停止(正確行為)
require_once __DIR__ . '/bootstrap.php';
// 可選功能:include 失敗記錄日誌但不中斷主流程
if (@include_once __DIR__ . '/plugins/analytics.php') {
Analytics::init();
} else {
error_log('Analytics plugin not found, skipping');
}
// 條件載入:include 允許運行時判斷
$theme = getUserTheme();
include_once __DIR__ . "/themes/{$theme}/functions.php";
常見錯誤與避坑
| 錯誤 | 後果 | 修正 |
| 類別檔用 include | 重複包含導致「Cannot redeclare class」 | 改用 require_once |
| 核心設定用 include | 檔案缺失靜默失效,後續報詭異錯誤 | 改用 require |
| 迴圈中用 require | 編譯期錯誤(不能在迴圈中 require 變數路徑) | 改用 include |
| 混用導致依賴混亂 | 難以追蹤載入順序、循環依賴 | 統一用 Composer 自動載入 |
| 忽略 OpCache 影響 | 開發環境以為 require 快,生產其實無差 | 理解 OpCache 機制,生產必開 |
總結:決策流程圖
需要包含檔案
│
├─ 是類別/介面/Trait/核心設定? → 是 → require_once
│
├─ 是模板/視圖/可選模組? → 是 → include_once
│
├─ 需在迴圈/條件中動態載入? → 是 → include
│
└─ 以上皆否 → require_once(預設最安全)
現代 PHP 開發:99% 場景由 Composer 自動載入處理,手寫 require/include 僅存在於入口檔、設定檔、模板渲染、動態模組載入等邊界場景。理解底層差異是為了在邊界場景做正確選擇。
- 上一篇文章: 基於 Nginx 的 PHP 本地測試環境構建工具 Pinyshop 發布
- 下一篇文章: 使用 CakePHP 模型檢索數據:從基礎到進階查詢
Copyright ©
程式碼之家 All Rights Reserved