预加载 PHP 脚本时"Unknown type dependencies"是什么意思?



我正在尝试使用自 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类来解决此问题。这是使用它来预加载LoaderInterfaceAnnotationClassLoder的方法:

<?php 
// preload.php
$classes[] = 'SymfonyComponentConfigLoaderLoaderInterface';
$classes[] = 'SymfonyComponentRoutingLoaderAnnotationClassLoader';
Preloader::preload($classes);

在有更好的方法之前,您可以复制该类或预加载库所依赖的所有类。


如果您允许预加载失败是硬错误,请使用 NikiC 的答案:

为避免依赖问题,您可以使用require而不是opcache_compile_file()进行预加载。这将很好地处理循环依赖项,但如果预加载失败(而不仅仅是警告(,则会出现硬错误。

相关内容

最新更新