我正在尝试使用自 PHP 7.4 以来可用的新预加载功能。
我运行composer install --no-dev --optimize-autoloader
生成项目中所有可用类的列表,并使用以下preload.php
脚本预加载它们:
$files = require 'vendor/composer/autoload_classmap.php';
foreach (array_unique($files) as $file) {
opcache_compile_file($file);
}
并在我的opcache.ini
文件中配置了这个预加载脚本:
opcache.preload=/path/to/preload.php
并重新启动php-fpm
.现在,systemctl status php-fpm.service
报告以下警告:
PHP 警告:无法预加载未链接的类 Brick\Money\Context\CashContext:未知类型的依赖项...在第 16 行
PHP 警告:无法预加载未链接的类砖\钱\上下文\自动上下文:未知类型的依赖项...在第 17 行
PHP 警告:无法预加载未链接的类 Brick\Math\BigRational:...在第 17 行
PHP 警告:无法预加载未链接的类 Brick\Math\BigInteger:...在第 20 行
PHP 警告:无法预加载未链接的类 砖\数学\大十进制:未知类型依赖...在第 15 行
"未知类型依赖项"是什么意思?如何预加载这些类?
注意:我是有问题的库 Brick\Math 和 Brick\Money 的维护者,所以如果这些库需要修改以使它们可预加载,我全都听!
这意味着 PHP 在运行时无法在预加载的文件中找到类。仅当可能存在不兼容的方法时,才会发生这种情况:
预加载:放宽已知类型限制
检查是否存在同名的父/接口/特征方法,然后才要求知道类型。这大大减少了在实践中触发这种情况的情况数量。
预加载的文件不使用 Composer 自动加载器,因此未预加载的类将不存在。
Symfony通过创建一个可以加载其依赖项的Preloader
类来解决此问题。这是使用它来预加载LoaderInterface
和AnnotationClassLoder
的方法:
<?php
// preload.php
$classes[] = 'SymfonyComponentConfigLoaderLoaderInterface';
$classes[] = 'SymfonyComponentRoutingLoaderAnnotationClassLoader';
Preloader::preload($classes);
在有更好的方法之前,您可以复制该类或预加载库所依赖的所有类。
如果您允许预加载失败是硬错误,请使用 NikiC 的答案:
为避免依赖问题,您可以使用
require
而不是opcache_compile_file()
进行预加载。这将很好地处理循环依赖项,但如果预加载失败(而不仅仅是警告(,则会出现硬错误。