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 且 opcache.enable=1 的前提下生效。注意:opcache.preload 配置项必须显式设置,不能依赖默认值(默认为空字符串,即不启用预加载)。
- 运行
php -v确认版本 ≥ 7.4 - 检查
php --ini找到主配置文件路径,打开后确认存在且未被注释:opcache.enable=1 opcache.preload=/path/to/preload.php
-
opcache.preload必须是绝对路径;相对路径或 ~ 符号均无效 - 修改后需重启 PHP-FPM 或 Apache/Nginx(不是 reload,是完整 restart)
编写 preload.php 文件:只 include,不 new,不调用业务逻辑
预加载脚本本质是“让 PHP 提前执行一遍 include”,但所有副作用操作(如实例化类、连接数据库、写日志)都必须排除——否则服务启动失败或行为异常。
- 只使用
require_once或include_once加载类文件(推荐前者) - 不要调用
class_exists()、function_exists()等运行时检测函数 - 禁止任何
new SomeClass()、SomeClass::init()、echo、file_get_contents()等 IO 或执行语句 - 若项目用 Composer,可直接加载
vendor/autoload.php,但需确保该文件本身不含副作用(现代 Composer 生成的 autoload.php 满足要求)
示例 preload.php:
<?php // 正确:纯加载 require_once '/var/www/app/Models/User.php'; require_once '/var/www/app/Services/CacheService.php'; require_once '/var/www/vendor/autoload.php'; // 错误:以下任一行为都会导致 preload 失败 // new User(); // CacheService::getInstance(); // echo 'preload loaded';
验证预加载是否生效
光看服务启动不报错不代表成功;必须确认类定义已进入预加载状态,且自动加载器(如 Composer 的 ClassLoader)已被绕过。
- 在任意 PHP 脚本中执行:
var_dump(opcache_is_script_cached('/var/www/app/Models/User.php'));—— 返回true表示该文件已被预加载 - 用 Xdebug 或 Blackfire 抓一次请求,观察自动加载器调用栈是否大幅减少(特别是
Composer\Autoload\ClassLoader::loadClass调用次数应趋近于 0) - 注意:预加载不解决类内方法执行慢的问题,只解决“找类”和“编译类”的开销
常见坑:PSR-4 自动加载路径与预加载冲突
当同时启用 Composer 的 PSR-4 自动加载和 OPcache 预加载时,容易出现“类重复定义”或“预加载失效”——根本原因是自动加载器仍会尝试加载已被预加载的类。
- 解决方案:在
composer.json中设置"autoload": {"classmap": [...]}替代部分 PSR-4 映射,再把 classmap 生成的文件加入 preload - 更稳妥做法:禁用 Composer 自动加载器对已预加载命名空间的处理,例如在
preload.php末尾添加:if (class_exists('Composer\Autoload\ClassLoader')) { $loader = \Composer\Autoload\ClassLoader::getRegisteredLoaders()[0] ?? null; if ($loader) { // 移除对预加载命名空间的处理(需按实际命名空间调整) $loader->unregister(); } } - 切勿在预加载脚本中调用
spl_autoload_register()或修改自动加载队列
预加载不是“开箱即用”的银弹:它要求你明确知道哪些类稳定、无副作用、高频使用;一旦预加载的类文件被修改,必须重启 PHP 进程才能生效——这点和普通 OPcache 缓存的文件热更新完全不同。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











