OPcache预加载是PHP 7.4+在服务器启动时将类文件编译并常驻内存的优化机制,需满足PHP≥7.4、opcache.enable=1且显式配置绝对路径的opcache.preload,preload.php中仅允许include_once/require_once,严禁任何副作用操作。
OPcache 预加载(Preloading)是 PHP 7.4 引入的核心优化机制,它能在 Web 服务器启动时一次性将指定类文件编译并常驻内存,彻底跳过后续每次请求的文件读取、解析、编译环节——这比普通 OPcache 缓存更进一步,直接消除自动加载开销。
确认 PHP 版本与 OPcache 是否启用
预加载仅在 PHP ≥ 7.4 且
的前提下生效。注意:
配置项必须显式设置,不能依赖默认值(默认为空字符串,即不启用预加载)。
运行
确认版本 ≥ 7.4
检查
找到主配置文件路径,打开后确认存在且未被注释:
必须是绝对路径;相对路径或 ~ 符号均无效
修改后需重启 PHP-FPM 或 Apache/Nginx(不是 reload,是完整 restart)
编写 preload.
php
文件:只 include,不 new,不调用业务逻辑
预加载脚本本质是“让 PHP 提前执行一遍
”,但所有副作用操作(如实例化类、连接数据库、写日志)都必须排除——否则服务启动失败或行为异常。
只使用
或
加载类文件(推荐前者)
不要调用
、
等运行时检测函数
禁止任何
、
、
、
等 IO 或执行语句
若项目用 Composer,可直接加载
,但需确保该文件本身不含副作用(现代 Composer 生成的 autoload.php 满足要求)
示例
:
立即学习
“
PHP免费学习笔记(深入)
”;
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
验证预加载是否生效
光看服务启动不报错不代表成功;必须确认类定义已进入预加载状态,且自动加载器(如 Composer 的
)已被绕过。
在任意 PHP 脚本中执行:
—— 返回
表示该文件已被预加载
用 Xdebug 或 Blackfire 抓一次请求,观察自动加载器调用栈是否大幅减少(特别是
调用次数应趋近于 0)
注意:预加载不解决类内方法执行慢的问题,只解决“找类”和“编译类”的开销
常见坑:PSR-4 自动加载路径与预加载冲突
当同时启用 Composer 的 PSR-4 自动加载和 OPcache 预加载时,容易出现“类重复定义”或“预加载失效”——根本原因是自动加载器仍会尝试加载已被预加载的类。
解决方案:在
中设置
替代部分 PSR-4 映射,再把 classmap 生成的文件加入 preload
更稳妥做法:禁用 Composer 自动加载器对已预加载命名空间的处理,例如在
末尾添加:
切勿在预加载脚本中调用
或修改自动加载队列
预加载不是“开箱即用”的银弹:它要求你明确知道哪些类稳定、无副作用、高频使用;一旦预加载的类文件被修改,必须重启 PHP 进程才能生效——这点和普通 OPcache 缓存的文件热更新完全不同。
opcache.enable=1opcache.preloadphp -vphp --iniopcache.enable=1
opcache.preload=/path/to/preload.phpopcache.preloadincluderequire_onceinclude_onceclass_exists()function_exists()new SomeClass()SomeClass::init()echofile_get_contents()vendor/autoload.phppreload.phpClassLoadervar_dump(opcache_is_script_cached('/var/www/app/Models/User.php'));trueComposer\Autoload\ClassLoader::loadClasscomposer.json"autoload": {"classmap": [...]}preload.phpif (class_exists('Composer\Autoload\ClassLoader')) {
$loader = \Composer\Autoload\ClassLoader::getRegisteredLoaders()[0] ?? null;
if ($loader) {
// 移除对预加载命名空间的处理(需按实际命名空间调整)
$loader->unregister();
}
}spl_autoload_register()