require_once报“No such file or directory”时,根本原因是PHP对./或../开头的路径跳过include_path查找,直接基于getcwd()拼接,而getcwd()不等于文件所在目录;应统一用__DIR__拼接绝对路径。

require_once 报错“No such file or directory”时,先看报错路径是不是相对路径
PHP 在解析 require_once 的路径时,对以 ./ 或 ../ 开头的路径会**跳过 include_path 查找逻辑**,直接按当前工作目录(getcwd())去拼接。但这个“当前工作目录”不一定是你写的那个 PHP 文件所在目录——它取决于 Web 服务器如何启动脚本,比如 Apache 的 DocumentRoot 或 CLI 下执行时的 shell 当前路径。
常见现象:在 index.php 里写 require_once('service/logic.php') 没问题;但 logic.php 内部又写 require_once('../config/db.php'),就报错。因为此时 PHP 是从 index.php 所在目录出发解析 ../config/db.php,而不是从 logic.php 自身位置出发。
- 用
echo getcwd();打印当前工作目录,确认它是否符合你对“相对路径起点”的预期 - 用
echo __DIR__;打印当前文件所在绝对路径,这是稳定可靠的基准点 - 避免在非入口文件中使用
../类路径,除非你明确控制了调用链的 cwd
用 __DIR__ 拼接绝对路径是最稳妥的写法
所有 require_once 路径都应该基于 __DIR__ 构建,而不是依赖当前工作目录或硬编码绝对路径。这样无论脚本从哪被调用,路径都指向它自己所在目录的相对位置。
例如,在 /app/service/auth.php 中要加载同级的 utils.php 和上层的 config.php:
立即学习“PHP免费学习笔记(深入)”;
// 正确:基于自身位置 require_once __DIR__ . '/utils.php'; // /app/service/utils.php require_once __DIR__ . '/../config.php'; // /app/config.php // 错误:依赖 cwd,不可靠 require_once '../config.php'; // 错误:硬编码,换环境就挂 require_once '/var/www/app/config.php';
-
__DIR__是魔术常量,编译期确定,性能无损耗 - 不要用
dirname(__FILE__)—— 它和__DIR__等价但更冗长,且易拼错 - 如果跨多级目录,可嵌套
dirname(__DIR__),但推荐直接用字符串拼接,更直观
include_path 设置失效?检查路径开头有没有 ./ 或 ../
当你设置了 set_include_path() 或修改了 php.ini 中的 include_path,却发现 require_once 'config.php' 还是找不到文件,大概率是因为你写的路径被 PHP 判定为“目录相对路径”了。
PHP 规则很明确:只要路径以 ./、../ 或 / 开头,就**不走 include_path 查找流程**,只按规则去解析那个字面路径。
- 想让
include_path生效,路径必须是纯文件名,如config.php,不能带任何路径分隔符 -
set_include_path(get_include_path() . PATH_SEPARATOR . __DIR__ . '/lib');后,再写require_once 'db.php'才会去/your/script/lib/db.php找 - 一旦写了
./db.php,哪怕include_path设得再全也无视
require_once 返回 1 而不是文件内容?说明文件已被加载过
这不是路径错误,但容易被误判为“没加载成功”。require_once 和 include_once 的语义是“只加载一次”,第二次调用时直接返回 int(1),不会报错也不会重复执行。
典型陷阱:
$cfg = require_once 'config.php'; // 第一次:返回 config.php 的 return 值(比如 array) $cfg = require_once 'config.php'; // 第二次:返回 int(1),覆盖原数组 var_dump($cfg); // int(1),不是配置数组
- 如果文件末尾有
return $value;,只在首次加载时生效 - 不要把
require_once当作函数调用赋值,尤其在循环或多次包含场景中 - 真需要多次获取值,改用
require(注意重复定义冲突)或封装成函数
__DIR__ 和 getcwd() 这两个锚点。多数线上故障,都是因为某处悄悄混用了二者。



















