简体   繁体   中英

What does “Unknown type dependencies” mean when preloading PHP scripts?

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 of opcache_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM