3

我正在尝试使用自 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 警告:无法预加载未链接的类 Brick\Money\Context\AutoContext:..中的未知类型依赖项. on line 17
PHP Warning: Can't preload unlinked class Brick\Math\BigRational: Unknown type dependencies in ... on line 17
PHP Warning: Can't preload unlinked class Brick\Math\BigInteger: Unknown type dependencies in ... . on line 20
PHP Warning: Can't preload unlinked class Brick\Math\BigDecimal: Unknown type dependencies in ... 第 15 行

“未知类型依赖”是什么意思?如何预加载这些类?

注意:我是有问题的库Brick\MathBrick\Money的维护者,所以如果需要修改这些库以使其可预加载,我会全力以赴!

4

1 回答 1

0

这意味着 PHP 在运行时无法在预加载文件中找到类。这只发生在可能存在不兼容的方法时

预加载:放宽已知类型限制
检查是否存在同名的父/接口/特征方法,然后才要求知道类型。这减少了在实践中大量触发的情况。

预加载的文件不使用 Composer 自动加载器,因此未预加载的类将不存在。

Symfony 通过创建一个Preloader可以加载其依赖项的类来解决这个问题。这是如何使用它来预加载LoaderInterfaceAnnotationClassLoder

<?php 
// preload.php
$classes[] = 'Symfony\Component\Config\Loader\LoaderInterface';
$classes[] = 'Symfony\Component\Routing\Loader\AnnotationClassLoader';

Preloader::preload($classes);

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


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

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

于 2019-12-29T15:35:22.487 回答