include、require、include_once、require_once 是 PHP 代碼復用的核心機制。雖然功能相似(引入並執行指定文件),但它們在**加載時機、錯誤級別、條件執行、性能**上存在關鍵差異。本文從底層原理到實戰場景全方位解析。
| 特性 | require | include | require_once | include_once |
|---|---|---|---|---|
| 加載時機 | **編譯階段**(腳本啟動前) | **運行階段**(執行到該行時) | 編譯階段 | 運行階段 |
| 文件不存在 | Fatal Error (E_COMPILE_ERROR),腳本**立即終止** | Warning (E_WARNING),腳本**繼續執行** | Fatal Error | Warning |
| 條件引入 | ❌ 無條件(編譯時已載入) | ✅ 支持(如 if($cond) include 'a.php';) | ❌ | ✅ |
| 重複引入 | 允許重複執行 | 允許重複執行 | 僅引入一次 | 僅引入一次 |
| 返回值處理 | 可接收被引文件 return 值 | 可接收 return 值 | 首次引入可接收 | 首次引入可接收 |
| 性能開銷 | 略低(編譯期完成) | 略高(運行期解析路徑、檢查) | 略高(需維護已載入表) | 略高 |
PHP 解析器在**編譯階段**遇到 require 會:
後果:
if(false) require 'a.php'; 中避免加載 —— 依然會編譯 a.php 並報錯(若不存在)。PHP 在**運行到該行**時才:
後果:
if($need) include "module_{$type}.php";內部維護一個「已加載文件實際路徑」哈希表(realpath() 後的路徑)。再次引入相同文件直接跳過。**注意**:符號鏈接、大小寫不敏感文件系統(Windows/macOS)下,不同路徑指向同一文件可能被重複加載。
require_once<?php
// bootstrap.php
require_once __DIR__ . '/config/database.php';
require_once __DIR__ . '/vendor/autoload.php'; // Composer 自動加載
require_once __DIR__ . '/core/Application.php';
理由:系統啟動必須依賴,缺失即致命錯誤,防止重複定義類/常量。
include<?php
// 動態加載支付網關
$gateway = $_GET['gateway'] ?? 'alipay';
$file = __DIR__ . "/gateways/{$gateway}.php";
if (is_file($file)) {
include $file; // 運行時決策,支持新增文件無需改代碼
$handler = new $gateway\Handler();
} else {
throw new Exception("不支持的網關: $gateway");
}
include<?php
// 內部可使用 $title, $content 變量
include __DIR__ . '/views/article.php';
// article.php 內容:
// <h1><?= $title ?></h1>
// <div><?= $content ?></div>
include/require<?php
// config.php
return [
'db' => ['host' => 'localhost', 'name' => 'test'],
'debug' => true,
];
// 使用
$config = include 'config.php'; // 接收 return 值
// 或
$config = require 'config.php'; // 同樣可接收
開啟 OPcache (opcache.enable=1) 後:
require/include 變為從內存獲取 opcode,**無磁盤 IO、無編譯開銷**。realpath)仍有微小開銷,可用絕對路徑或常量 __DIR__ 避免。建議:生產環境**必須開啟 OPcache**,此時四者性能差異可忽略,優先考慮語義正確性。
include 'a.php' 相對「當前工作目錄」(getcwd()),非腳本所在目錄。統一使用 __DIR__ . '/a.php'。require 在函數中導致作用域隔離function loadConfig() {
require 'config.php'; // config.php 中的 $config 變成局部變量!
return $config; // 必須返回
}
$config = loadConfig();
include_path,顯式指定完整路徑,提高可讀性與性能。現代 PHP 項目**不再手寫 require/include 業務類**,而是:
// composer.json
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
// 執行 composer dump-autoload
// 入口文件唯一 require
require_once __DIR__ . '/vendor/autoload.php';
// 之後直接使用
use App\Controller\UserController;
use App\Model\User;
優勢:零配置按需加載、統一命名規範、支持開發環境熱更新、生產環境優化類映射表(classmap)。
__DIR__ 構建絕對路徑。