../路径不走include_path,直接从getcwd()返回的当前工作目录解析;而无前缀路径会依次在include_path、入口脚本目录、cwd中查找;__dir__拼接可避免cwd依赖,更安全。

../ 在 include 中的解析规则
PHP 把以 ../ 开头的路径视为「目录相对路径」,它**不走 include_path 查找逻辑**,而是直接从「当前工作目录(CWD)」出发向上回溯。注意:这个「当前工作目录」不是文件所在目录,也不是入口脚本目录,而是 PHP 进程启动时所在的目录(比如 Apache 的 DocumentRoot、CLI 下执行 php index.php 时你所在的 shell 目录)。
常见错误现象:
- Web 下访问
/public/index.php,但index.php里写include '../config/db.php',报错Failed opening required '../config/db.php' - CLI 下在项目根目录运行
php src/cli.php,cli.php中include '../vendor/autoload.php'成功;但换到src/目录下运行就失败
关键点:
-
../的起点是getcwd()返回的路径,不是__DIR__ - 符号链接(symlink)会让
getcwd()行为更不可控——Apache/Nginx 经常通过 symlink 指向真实路径,但 CWD 仍是 symlink 所在目录 - 不同 SAPI(CLI / Apache / FPM)对 CWD 的初始化方式不同,行为不一致
require '../xxx.php' 和 require 'xxx.php' 的本质区别
这两个写法触发的是完全不同的查找机制:
-
require '../xxx.php':属于「目录相对路径」,跳过include_path,只在getcwd()下解析../xxx.php -
require 'xxx.php':属于「未确定路径(unqualified path)」,PHP 会依次在:include_path各目录 → 入口脚本所在目录 → 当前工作目录,三处查找
所以它们根本不是「相对 vs 绝对」的对比,而是「强制 CWD 解析」vs「多级 fallback 查找」的区别。这也是为什么很多人改了 include_path 却发现 ../ 写法完全不受影响——因为压根没走到那步。
为什么 __DIR__ . '/../lib/foo.php' 是更安全的替代方案
用 __DIR__ 明确锚定到当前文件所在目录,再拼接路径,彻底摆脱对 getcwd() 的依赖:
访问全球海洋潮汐模型。功能包括查询指定日期、时间和地点的潮高、潮汐极值及格点天气数据。
require __DIR__ . '/../lib/utils.php';
这样无论脚本被谁调用、在哪儿执行、是否经过 symlink,只要文件结构不变,路径就稳。
注意事项:
-
__DIR__是魔术常量,返回不含尾部斜杠的绝对路径(如/var/www/project/src),拼接时要自己加/ - 避免写成
__DIR__.'/../lib/utils.php'(少空格易读错),建议统一用__DIR__ . '/..' . '/lib/utils.php'或dirname(__DIR__) . '/lib/utils.php' - 如果目标文件可能不存在,建议加
file_exists()判断或用realpath()验证后再require,否则直接报致命错误
include_path 对 ../ 路径完全无效的底层原因
PHP 源码中,../ 这类路径会直接进入 _php_stream_fopen_with_path 的「skip include_path」分支。一旦路径以 . 或 / 开头(Windows 下还包含盘符),PHP 就认定这是用户明确指定的路径,不再尝试 include_path 列表中的任何目录。
这意味着:
- 你在
php.ini里把include_path设成.:/opt/lib:/usr/share/php,对include '../config.php'完全无感 -
set_include_path()动态修改也无效 - 哪怕你用
ini_set('include_path', ...),只要路径带../,照样忽略
这种设计本意是避免歧义,但实际成了最容易被误用的陷阱——开发者以为改了 include_path 就能统一管理路径,结果 ../ 写法让所有配置形同虚设。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










