PHP 提供四種檔案引入語句,新手常混淆它們的錯誤等級、重複引入行為與編譯時機。本文用一張表說清核心差異,並深入解析底層機制與最佳實踐。
| 語句 | 找不到檔案時 | 重複引入同一檔案 | 編譯/執行時機 | 典型用途 |
|---|---|---|---|---|
require |
致命錯誤,腳本停止 | 重複執行(可能導致函數重複定義錯誤) | 編譯期(PHP 4+ 整體編譯後執行) | 核心配置、必要類別、關鍵函數庫 |
require_once |
致命錯誤,腳本停止 | 忽略(僅引入一次) | 編譯期 | 類別定義、介面、Trait、函數庫(防重複) |
include |
警告,腳本繼續 | 重複執行 | 執行期(遇到該行才引入) | 模板檔案、可選模組、條件性引入 |
include_once |
警告,腳本繼續 | 忽略(僅引入一次) | 執行期 | 可選類別、插件系統、條件性防重複 |
E_COMPILE_ERROR,腳本立即終止,後續代碼不執行。適用於「沒有這個檔案系統就跑不動」的場景。E_WARNING,腳本繼續執行。適用於「檔案可有可無、缺了也不影響主流程」的場景(如廣告模組、側邊欄)。PHP 4.0+ 採用「先整體編譯,再執行」模式。
require 在編譯階段就將目標檔案內容「展開」到當前位置。因此不能在 if、for、函數內動態決定路徑(雖然語法允許,但行為違背直覺)。include 在執行到該行時才引入,支援動態路徑、條件判斷、循環中引入不同檔案。<?php
// 動態引入:只能用 include
$module = $_GET['mod'] ?? 'default';
include "modules/{$module}.php"; // 正確
// require 在編譯期處理,變數尚未賦值
// require "modules/{$module}.php"; // 不推薦,行為難預測
?>
PHP 內部維護一個「已引入檔案絕對路徑」集合(realpath() 正規化後)。require_once / include_once 檢查該集合,已存在則跳過。
Cannot redeclare function/class 致命錯誤。realpath 可能導致誤判。建議專案統一路徑大小寫。require 'vendor/autoload.php' 一次性載入自動載入器,其餘靠命名空間與 use 解析。require_onceinclude(因同一模板可能在不同邏輯下多次渲染)include_once__DIR__ 或 DIR 定義路徑,避免相對路徑在 include 鏈中失效。
require_once __DIR__ . '/../config/database.php';
include 或預先收集路徑陣列再循環 include_once。標準答案:require 是編譯期指令,將檔案內容靜態嵌入;include 是執行期指令,動態引入並執行。缺少檔案時前者致命錯誤停止,後者警告繼續。
核心必載用 require,防重複加 _once;
模板可選用 include,防重複也加 _once。
現代專案靠 Composer,自動載入最省心。
理解這些細節,能讓你在除錯「找不到檔案」、「函數重複定義」、「變數作用域洩漏」等經典問題時,快速定位根因並做出正確架構決策。