require失败导致脚本立即终止,无法用try/catch或@抑制;file_exists存在TOCTOU风险,推荐is_readable或白名单映射;require_once不解决文件缺失问题,仅防重复加载。

Fatal error: require(): Failed opening required —— 这不是 warning,不能 catch,脚本当场终止。你后面写的任何代码都不会执行。
require 文件不存在直接中断执行
require 是语言结构,不是函数,它在解析阶段就要求目标文件必须存在且可读。一旦失败,PHP 立即抛出 Fatal error,整个请求生命周期结束。这和 include 的行为有本质区别:include 只报 Warning,后续代码还能跑。
- 错误信息典型格式:
Fatal error: require(): Failed opening required '/path/to/file.php' (include_path='.:/usr/share/php') - 无法用
try/catch捕获,因为这不是异常(Exception),而是编译/执行期致命错误 -
@require无效——@只能抑制 warning 和 notice,对 fatal error 完全没用 - 即使
require写在if (false) { }块里,现代 PHP(5.0+)也不会提前加载,但只要执行流走到那一行,就立刻崩
为什么不能用 file_exists 做前置判断
file_exists 看起来能预防,但它只检查路径存在性,不校验读权限或是否为合法 PHP 文件。更危险的是:它和 require 之间存在 TOCTOU(Time-of-Check to Time-of-Use)竞态窗口——文件可能在 file_exists 返回 true 后、require 执行前被删掉或改名。
- 推荐改用
is_readable:它同时检查存在性和读权限,比file_exists更贴近require的实际需求 - 但注意:
is_readable仍无法完全消除竞态,只是显著降低概率 - 真正安全的方案是重构逻辑:把动态路径转为白名单映射,或用
stream_resolve_include_path预查路径有效性(它返回绝对路径或false,不触发加载)
require_once 对不存在的文件也无效
require_once 的 “once” 仅针对**已成功加载过的文件**。如果第一次 require_once 'missing.php' 就失败了,那它根本不会被记入“已加载列表”,下次再调同样的语句,照样报 fatal error。
立即学习“PHP免费学习笔记(深入)”;
- 也就是说:
require_once不会跳过对缺失文件的检查,也不会缓存“这个文件找不到”的结果 - 它只防止重复加载**同一个成功引入的文件**,比如避免两次定义同名类导致
Fatal error: Cannot declare class - 如果你依赖
require_once来“兜底”,那是个常见误解——它不解决文件不存在问题,只解决重复包含问题
最常被忽略的一点:require 的路径解析依赖 include_path,而这个配置可能让开发者误以为相对路径是“当前文件所在目录”,其实它是从 getcwd() 或配置的 include_path 列表依次查找。线上环境和本地开发路径不一致时,这个差异最容易引发“本地好好的,一上线就 fatal”。



















