phpsymfonyopcacheplatform.sh

Opcache Preloading with Symfony 5.4 / PHP8 / Platform.sh


I am attempting to set up Opcache Preloading on Symfony 5.4 running on PHP8 at Platform.sh, and running into a fatal error.

Configuration

Necessary pieces included:

// platform.app.yaml
...
variables
  php
    'opcache.preload': 'var/cache/prod/App_KernelProdContainer.php'
...

hooks:
  build: |
    ...
    composer dump-autoload --no-dev --classmap-authoritative
  deploy: |
    ...
    sv restart app
...

I can verify that the App_KernelProdContainer.php file is being created at the correct location defined in the config above:

<?php

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.

if (\class_exists(\ContainerF9HiXre\App_KernelProdContainer::class, false)) {
    // no-op
} elseif (!include __DIR__.'/ContainerF9HiXre/App_KernelProdContainer.php') {
    touch(__DIR__.'/ContainerF9HiXre.legacy');

    return;
}

if (!\class_exists(App_KernelProdContainer::class, false)) {
    \class_alias(\ContainerF9HiXre\App_KernelProdContainer::class, App_KernelProdContainer::class, false);
}

return new \ContainerF9HiXre\App_KernelProdContainer([
    'container.build_hash' => 'F9HiXre',
    'container.build_id' => '98091d49',
    'container.build_time' => 1644501054,
], __DIR__.\DIRECTORY_SEPARATOR.'ContainerF9HiXre');

The included file ContainerF9HiXre/App_KernelProdContainer.php throws errors on the use statements like this:

Fatal error:  Uncaught Error: Class &quot;Symfony\Component\DependencyInjection\Container&quot; not found in /app/var/cache/prod/ContainerF9HiXre/App_KernelProdContainer.php:17
Stack trace:
#0 /app/var/cache/prod/App_KernelProdContainer.php(7): include()
#1 {main}
  thrown in /app/var/cache/prod/ContainerF9HiXre/App_KernelProdContainer.php on line 17

Use statements in the included file appear as such:

namespace ContainerF9HiXre;

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

Solution

  • You seem to be using the wrong file for preloading.

    The generated file is named something like srcApp_KernelProdContainer.preload.php. But in any case, you probably should't be adding this file directly to opcache.preload, but the Symfony generated config/preload.php.

    Since on platform.sh the path is resolved relative to the project root, you can use a relative path like this:

    opcache.preload=config/preload.php
    

    If you do not have this file (e.g. incomplete recipes), you could simply re-generate it by running composer recipes:update symfony/framework-bundle, as explained here.

    Or, ir you are not using Symfony Flex and want to do it manually, you can simply copy the file from the appropriate recipe, like this one.

    It's a very simple script in any case:

    <?php
    
    if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
        require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
    }