PHP 包含

include vs require, the _once variants, and locating files with __DIR__.

Beginner
Key Points`include` warns on failure, `require` is fatal; locate files with `__DIR__`.

The four statements

StatementOn failureRuns againUse for
include警告,继续执行会可选片段、模板
include_once警告,继续执行不会函数/类定义
require致命错误,终止会必需依赖
require_once致命错误,终止不会配置、库、类文件

**Real projects mostly use require_once**: failing fast beats running half a system, and _once prevents duplicate definitions.

Return values

An included file may return, and include hands the value back — letting config files return arrays.

PHP
<?php
// 动态写一个模块文件,模拟「被包含的文件」
$mod = __DIR__ . "/_mod.php";
file_put_contents($mod, '<?php return ["site" => "我的站点", "ver" => "1.0"];');

$conf = include $mod;
echo $conf["site"] . " " . $conf["ver"], "\n";

$again = include $mod;
echo $conf === $again ? "内容一致" : "内容不同", "\n";

require $mod;
echo "require 执行完毕\n";

include_once $mod;
echo "include_once 跳过\n";

unlink($mod);
echo file_exists($mod) ? "文件还在" : "临时文件已清理", "\n";
Output
我的站点 1.0
内容一致
require 执行完毕
include_once 跳过
临时文件已清理

require $mod; as a statement discards the value. Assign it to capture: $x = require $mod;.

Variable scope

An included file inherits the including scope — unlike a function. That is exactly how template engines work.

PHP
<?php
$mod = __DIR__ . "/_tpl.php";
file_put_contents($mod, '<h1><?= $title ?></h1>');

$title = "页面标题";
include $mod;
echo "\n";

function render(string $tpl, array $vars): void {
    extract($vars);          // 把数组变成局部变量
    include $tpl;
}
render($mod, ["title" => "函数里的标题"]);
echo "\n";

unlink($mod);
Output
<h1>页面标题</h1>
<h1>函数里的标题</h1>
extract() turns keys into variables — calling it on external data is a backdoor. Use it only inside templates with trusted input.

Locating with __DIR__

PHP
<?php
// 受工作目录影响,容易找不到
// require "config.php";

// 始终相对本文件
$path = __DIR__ . "/config.php";
echo basename($path), "\n";

// 相对本文件的上一级
$up = dirname(__DIR__) . "/shared/config.php";
echo basename(dirname($up)) . "/" . basename($up), "\n";

// 推荐:用常量表达项目根
define("BASE_PATH", dirname(__DIR__));
echo basename(BASE_PATH), "\n";
Output
config.php
shared/config.php
demo

With the file at /var/www/demo/inc/bootstrap.php, __DIR__ is .../inc and dirname(__DIR__) is .../demo. Define BASE_PATH once and build every require on it.

Autoloading instead

Class files need no manual require. Register an autoloader and each class loads on first use — exactly what Composer's vendor/autoload.php does.

PHP
<?php
require __DIR__ . "/vendor/autoload.php";

// 之后直接用类,不需要 require 每个文件
$app = new App\Kernel();
echo get_class($app), "\n";
Output
App\Kernel
Walls of require_once are PHP 5 style. Modern projects have exactly one require __DIR__ . "/vendor/autoload.php";.

Friends & Partners