I'm attempting to make use of the new preloading feature available since PHP 7.4.
I ran composer install --no-dev --optimize-autoloader
to generate a list of all available classes in the project, and used the following preload.php
script to preload them:
$files = require 'vendor/composer/autoload_classmap.php';
foreach (array_unique($files) as $file) {
opcache_compile_file($file);
}
And configured this preload script in my opcache.ini
file:
opcache.preload=/path/to/preload.php
And restarted php-fpm
. Now systemctl status php-fpm.service
reports the following warnings:
PHP Warning: Can't preload unlinked class Brick\\Money\\Context\\CashContext: Unknown type dependencies in ... on line 16
PHP Warning: Can't preload unlinked class Brick\\Money\\Context\\AutoContext: Unknown type dependencies in ... 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 ... on line 15
What does "Unknown type dependencies" mean ? How can I get these classes preloaded?
Note: I'm the maintainer of the offending libraries Brick\\Math and Brick\\Money , so if these are in need of modifications to make them preloadable, I'm all ears!
It means that PHP couldn't find a class in a preloaded file at runtime. This only happens when there might be methods that are incompatible :
Preloading: Relax known type restrictions
Check whether there is a parent/interface/trait method with the same name and only then require the type to be known. This reduces the number of cases where this triggers in practice a lot.
Preloaded files don't use the Composer autoloader, so classes that don't get preloaded won't exist.
Symfony fixed this by creating a Preloader
class that can load its dependencies. This is how to use it to preload LoaderInterface
and AnnotationClassLoder
:
<?php
// preload.php
$classes[] = 'Symfony\Component\Config\Loader\LoaderInterface';
$classes[] = 'Symfony\Component\Routing\Loader\AnnotationClassLoader';
Preloader::preload($classes);
Until there's a better way to do it, you can copy that class or preload all classes that the library depends on.
If you can allow preloading failures to be hard errors, use the answer from NikiC :
To avoid dependency issues, you can preload using
require
instead ofopcache_compile_file()
. This will handle circular dependencies fine, but will hard error if preloading fails (instead of just warning).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.