PHP中__DIR__路径大小写差异导致文件重复引入问题
我的项目要求bootstrap.php仅被引入一次,在绝大多数开发环境中都能正常工作,但在一台Mac(通过brew安装PHP 8.1)的机器上,因路径大小写差异导致文件被重复引入。
路径大小写差异示例:
/Users/johndoe/desktop/projects/project_name/bootstrap.php vs /Users/johndoe/Desktop/Projects/project_name/bootstrap.php
最简复现场景:
根文件build.php代码:
// build.php ... dump(__DIR__); include "includes/content.php"; ...
includes/content.php顶部代码:
// top of includes/content.php dump(__DIR__); ...
输出结果:
/Users/johndoe/Desktop/Projects /Users/johndoe/desktop/projects/includes
我有多年PHP开发经验,从未遇到过这类问题。
环境信息:
- Mac + brew
- PHP 8.1
1. 统一代码中路径引用的大小写
直接排查项目内所有文件包含、路径引用的代码,确保书写的路径大小写和文件系统实际存储的完全一致(可通过终端ls -l命令查看系统实际路径的大小写),这是最直接的根治方法。
2. 用规范化路径配合单次引入函数
在包含文件前,先用realpath()获取系统实际的规范化路径(该函数会返回文件系统存储的真实大小写路径),再配合include_once/require_once使用:
$bootstrapPath = realpath(__DIR__ . '/bootstrap.php'); include_once $bootstrapPath;
即使传入的原始路径大小写混乱,realpath()会统一为系统真实路径,再通过include_once的去重逻辑,确保文件只被引入一次。
3. 调整文件系统为大小写敏感(谨慎操作)
若为本地开发环境,可将项目所在磁盘分区改为大小写敏感格式,但此操作可能影响其他依赖大小写不敏感的应用,操作前务必备份数据。可通过磁盘工具创建大小写敏感的镜像分区,或重装系统时选择对应格式。
问题原理
Mac默认的APFS文件系统是大小写不敏感但保留大小写:实际访问时Desktop和desktop指向同一个目录,但PHP的文件包含机制会以路径大小写作为区分文件的依据——哪怕实际是同一个文件,只要传入的路径大小写不同,PHP就会判定为不同文件,从而绕过include_once的去重逻辑,导致重复引入。
内容的提问来源于stack exchange,提问作者Jeroen de Lau

