diff --git a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php index 70cb05341c75..0204df05be7f 100644 --- a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php @@ -24,6 +24,9 @@ use Twig\TokenParser\AbstractTokenParser; use Twig\TwigFilter; +// Help opcache.preload discover always-needed symbols +class_exists(TranslatorInterface::class); + /** * Provides integration of the Translation component with Twig. * diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index ed85fa2ea758..931ca33285f1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -23,6 +23,11 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; +use Symfony\Component\Cache\Adapter\ApcuAdapter; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\ChainAdapter; +use Symfony\Component\Cache\Adapter\PhpArrayAdapter; +use Symfony\Component\Cache\Adapter\PhpFilesAdapter; use Symfony\Component\Cache\DependencyInjection\CacheCollectorPass; use Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass; use Symfony\Component\Cache\DependencyInjection\CachePoolPass; @@ -32,6 +37,7 @@ use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Compiler\RegisterReverseContainerPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Dotenv\Dotenv; use Symfony\Component\ErrorHandler\ErrorHandler; use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; use Symfony\Component\Form\DependencyInjection\FormPass; @@ -58,6 +64,19 @@ use Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass; use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass; +use Symfony\Component\VarExporter\Internal\Hydrator; +use Symfony\Component\VarExporter\Internal\Registry; + +// Help opcache.preload discover always-needed symbols +class_exists(ApcuAdapter::class); +class_exists(ArrayAdapter::class); +class_exists(ChainAdapter::class); +class_exists(PhpArrayAdapter::class); +class_exists(PhpFilesAdapter::class); +class_exists(Dotenv::class); +class_exists(ErrorHandler::class); +class_exists(Hydrator::class); +class_exists(Registry::class); /** * Bundle. diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php index 08628f4060d1..8971e5330b00 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php @@ -20,10 +20,15 @@ use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; +use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Router as BaseRouter; +// Help opcache.preload discover always-needed symbols +class_exists(RedirectableCompiledUrlMatcher::class); +class_exists(Route::class); + /** * This Router creates the Loader only when the cache is empty. * diff --git a/src/Symfony/Bundle/TwigBundle/TwigBundle.php b/src/Symfony/Bundle/TwigBundle/TwigBundle.php index 5a353833eb27..8b214bcf8e34 100644 --- a/src/Symfony/Bundle/TwigBundle/TwigBundle.php +++ b/src/Symfony/Bundle/TwigBundle/TwigBundle.php @@ -20,6 +20,20 @@ use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; +use Twig\Cache\FilesystemCache; +use Twig\Extension\CoreExtension; +use Twig\Extension\EscaperExtension; +use Twig\Extension\OptimizerExtension; +use Twig\Extension\StagingExtension; +use Twig\ExtensionSet; + +// Help opcache.preload discover always-needed symbols +class_exists(FilesystemCache::class); +class_exists(CoreExtension::class); +class_exists(EscaperExtension::class); +class_exists(OptimizerExtension::class); +class_exists(StagingExtension::class); +class_exists(ExtensionSet::class); /** * Bundle. diff --git a/src/Symfony/Component/Cache/Adapter/AdapterInterface.php b/src/Symfony/Component/Cache/Adapter/AdapterInterface.php index c40ae42b55fa..fbc74cae7901 100644 --- a/src/Symfony/Component/Cache/Adapter/AdapterInterface.php +++ b/src/Symfony/Component/Cache/Adapter/AdapterInterface.php @@ -14,6 +14,9 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\CacheItem; +// Help opcache.preload discover always-needed symbols +class_exists(CacheItem::class); + /** * Interface for adapters managing instances of Symfony's CacheItem. * diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 00bacd2ac6de..d098d614fff4 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -11,6 +11,8 @@ namespace Symfony\Component\DependencyInjection; +use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; +use Symfony\Component\DependencyInjection\Argument\ServiceLocator as ArgumentServiceLocator; use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; @@ -22,6 +24,10 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Contracts\Service\ResetInterface; +// Help opcache.preload discover always-needed symbols +class_exists(RewindableGenerator::class); +class_exists(ArgumentServiceLocator::class); + /** * Container is a dependency injection container. * diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 6915579893e1..982472f5adf0 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -81,6 +81,7 @@ class PhpDumper extends Dumper private $inlinedRequires = []; private $circularReferences = []; private $singleUsePrivateIds = []; + private $preload = []; private $addThrow = false; private $addGetService = false; private $locatedIds = []; @@ -142,6 +143,7 @@ public function dump(array $options = []) 'hot_path_tag' => 'container.hot_path', 'inline_factories_parameter' => 'container.dumper.inline_factories', 'inline_class_loader_parameter' => 'container.dumper.inline_class_loader', + 'preload_classes' => [], 'service_locator_tag' => 'container.service_locator', 'build_time' => time(), ], $options); @@ -226,8 +228,12 @@ public function dump(array $options = []) $proxyClasses = $this->inlineFactories ? $this->generateProxyClasses() : null; + if ($options['preload_classes']) { + $this->preload = array_combine($options['preload_classes'], $options['preload_classes']); + } + $code = - $this->startClass($options['class'], $baseClass, $preload). + $this->startClass($options['class'], $baseClass). $this->addServices($services). $this->addDeprecatedAliases(). $this->addDefaultParametersMethod() @@ -302,7 +308,7 @@ public function dump(array $options = []) $id = hash('crc32', $hash.$time); $this->asFiles = false; - if ($preload && null !== $autoloadFile = $this->getAutoloadFile()) { + if ($this->preload && null !== $autoloadFile = $this->getAutoloadFile()) { $autoloadFile = substr($this->export($autoloadFile), 2, -1); $code[$options['class'].'.preload.php'] = <<preload as $class) { + if (!$class || false !== strpos($class, '$')) { + continue; + } + if (!(class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) || (new \ReflectionClass($class))->isUserDefined()) { + $code[$options['class'].'.preload.php'] .= sprintf("\$classes[] = '%s';\n", $class); + } } $code[$options['class'].'.preload.php'] .= <<<'EOF' @@ -367,6 +378,7 @@ public function dump(array $options = []) $this->circularReferences = []; $this->locatedIds = []; $this->exportedVariables = []; + $this->preload = []; $unusedEnvs = []; foreach ($this->container->getEnvCounters() as $env => $use) { @@ -542,8 +554,10 @@ private function addServiceInclude(string $cId, Definition $definition): string if ($this->inlineRequires && (!$this->isHotPath($definition) || $this->getProxyDumper()->isProxyCandidate($definition))) { $lineage = []; foreach ($this->inlinedDefinitions as $def) { - if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) { - $this->collectLineage($class, $lineage); + if (!$def->isDeprecated()) { + foreach ($this->getClasses($def) as $class) { + $this->collectLineage($class, $lineage); + } } } @@ -552,9 +566,10 @@ private function addServiceInclude(string $cId, Definition $definition): string && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior && $this->container->has($id) && $this->isTrivialInstance($def = $this->container->findDefinition($id)) - && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass()) ) { - $this->collectLineage($class, $lineage); + foreach ($this->getClasses($def) as $class) { + $this->collectLineage($class, $lineage); + } } } @@ -804,6 +819,12 @@ protected function {$methodName}($lazyInitialization) if ($definition->isDeprecated()) { $code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id))); + } else { + foreach ($this->inlinedDefinitions as $def) { + foreach ($this->getClasses($def) as $class) { + $this->preload[$class] = $class; + } + } } if ($this->getProxyDumper()->isProxyCandidate($definition)) { @@ -960,7 +981,15 @@ private function addServices(array &$services = null): string $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { - $services[$id] = $definition->isSynthetic() ? null : $this->addService($id, $definition); + if (!$definition->isSynthetic()) { + $services[$id] = $this->addService($id, $definition); + } else { + $services[$id] = null; + + foreach ($this->getClasses($definition) as $class) { + $this->preload[$class] = $class; + } + } } foreach ($definitions as $id => $definition) { @@ -1061,7 +1090,7 @@ private function addNewInstance(Definition $definition, string $return = '', str return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail; } - private function startClass(string $class, string $baseClass, ?array &$preload): string + private function startClass(string $class, string $baseClass): string { $namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : ''; @@ -1124,7 +1153,7 @@ public function __construct() $code .= $this->addMethodMap(); $code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : ''; $code .= $this->addAliases(); - $code .= $this->addInlineRequires($preload); + $code .= $this->addInlineRequires(); $code .= <<hotPathTag || !$this->inlineRequires) { return ''; @@ -1342,8 +1371,7 @@ private function addInlineRequires(?array &$preload): string $inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]); foreach ($inlinedDefinitions as $def) { - if (\is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) { - $preload[$class] = $class; + foreach ($this->getClasses($def) as $class) { $this->collectLineage($class, $lineage); } } @@ -2065,4 +2093,29 @@ private function getAutoloadFile(): ?string return null; } + + private function getClasses(Definition $definition): array + { + $classes = []; + + while ($definition instanceof Definition) { + $classes[] = trim($definition->getClass(), '\\'); + $factory = $definition->getFactory(); + + if (!\is_array($factory)) { + $factory = [$factory]; + } + + if (\is_string($factory[0])) { + if (false !== $i = strrpos($factory[0], '::')) { + $factory[0] = substr($factory[0], 0, $i); + } + $classes[] = trim($factory[0], '\\'); + } + + $definition = $factory[0]; + } + + return array_filter($classes); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 2bbf46c906b9..1845785fb544 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -531,6 +531,24 @@ class ProjectServiceContainer extends Container } } + [ProjectServiceContainer.preload.php] => */ diff --git a/src/Symfony/Component/HttpFoundation/AcceptHeader.php b/src/Symfony/Component/HttpFoundation/AcceptHeader.php index bbbd62a6d28a..c3c8d0c3560e 100644 --- a/src/Symfony/Component/HttpFoundation/AcceptHeader.php +++ b/src/Symfony/Component/HttpFoundation/AcceptHeader.php @@ -11,6 +11,9 @@ namespace Symfony\Component\HttpFoundation; +// Help opcache.preload discover always-needed symbols +class_exists(AcceptHeaderItem::class); + /** * Represents an Accept-* header. * diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index bff1c0cbfad7..a5e50eb795a5 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -15,6 +15,14 @@ use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; use Symfony\Component\HttpFoundation\Session\SessionInterface; +// Help opcache.preload discover always-needed symbols +class_exists(AcceptHeader::class); +class_exists(FileBag::class); +class_exists(HeaderBag::class); +class_exists(HeaderUtils::class); +class_exists(ParameterBag::class); +class_exists(ServerBag::class); + /** * Request represents an HTTP request. * diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index b267cd8ceb57..714109d53669 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -11,6 +11,9 @@ namespace Symfony\Component\HttpFoundation; +// Help opcache.preload discover always-needed symbols +class_exists(ResponseHeaderBag::class); + /** * Response represents an HTTP response. * diff --git a/src/Symfony/Component/HttpFoundation/Session/Session.php b/src/Symfony/Component/HttpFoundation/Session/Session.php index 2192c629e896..b6973aaabb98 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Session.php +++ b/src/Symfony/Component/HttpFoundation/Session/Session.php @@ -18,6 +18,11 @@ use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; +// Help opcache.preload discover always-needed symbols +class_exists(AttributeBag::class); +class_exists(FlashBag::class); +class_exists(SessionBagProxy::class); + /** * @author Fabien Potencier * @author Drak diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 93a5d54e4dd2..54933d953af3 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -17,6 +17,11 @@ use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; +// Help opcache.preload discover always-needed symbols +class_exists(MetadataBag::class); +class_exists(StrictSessionHandler::class); +class_exists(SessionHandlerProxy::class); + /** * This provides a base class for session attribute storage. * diff --git a/src/Symfony/Component/HttpKernel/HttpClientKernel.php b/src/Symfony/Component/HttpKernel/HttpClientKernel.php index c8421a4b1041..912ce313f832 100644 --- a/src/Symfony/Component/HttpKernel/HttpClientKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpClientKernel.php @@ -21,6 +21,9 @@ use Symfony\Component\Mime\Part\TextPart; use Symfony\Contracts\HttpClient\HttpClientInterface; +// Help opcache.preload discover always-needed symbols +class_exists(ResponseHeaderBag::class); + /** * An implementation of a Symfony HTTP kernel using a "real" HTTP client. * diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index f1b601361e79..681e96321d03 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -33,6 +33,18 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +// Help opcache.preload discover always-needed symbols +class_exists(LegacyEventDispatcherProxy::class); +class_exists(ControllerArgumentsEvent::class); +class_exists(ControllerEvent::class); +class_exists(ExceptionEvent::class); +class_exists(FinishRequestEvent::class); +class_exists(RequestEvent::class); +class_exists(ResponseEvent::class); +class_exists(TerminateEvent::class); +class_exists(ViewEvent::class); +class_exists(KernelEvents::class); + /** * HttpKernel notifies events to convert a Request object to a Response one. * diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 6c8f019c6e99..d6f5a462d6e9 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -38,6 +38,9 @@ use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; +// Help opcache.preload discover always-needed symbols +class_exists(ConfigCache::class); + /** * The Kernel is the heart of the Symfony system. * @@ -805,6 +808,7 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container 'as_files' => true, 'debug' => $this->debug, 'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(), + 'preload_classes' => array_map('get_class', $this->bundles), ]); $rootCode = array_pop($content); diff --git a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php index 9a64565c523a..6248090820bb 100644 --- a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php +++ b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php @@ -22,6 +22,11 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\ProviderNotFoundException; +// Help opcache.preload discover always-needed symbols +class_exists(AuthenticationEvents::class); +class_exists(AuthenticationFailureEvent::class); +class_exists(AuthenticationSuccessEvent::class); + /** * AuthenticationProviderManager uses a list of AuthenticationProviderInterface * instances to authenticate a Token. diff --git a/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php b/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php index ca15a4042517..0deff425b798 100644 --- a/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php +++ b/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php @@ -14,6 +14,9 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; +// Help opcache.preload discover always-needed symbols +class_exists(ExpressionLanguageProvider::class); + if (!class_exists(BaseExpressionLanguage::class)) { throw new \LogicException(sprintf('The "%s" class requires the "ExpressionLanguage" component. Try running "composer require symfony/expression-language".', ExpressionLanguage::class)); } else { diff --git a/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php index 0f1da391e6df..999796d36803 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php @@ -19,6 +19,9 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; +// Help opcache.preload discover always-needed symbols +class_exists(AnonymousToken::class); + /** * AnonymousAuthenticationListener automatically adds a Token if none is * already present. diff --git a/src/Symfony/Component/Security/Http/Firewall/LegacyListenerTrait.php b/src/Symfony/Component/Security/Http/Firewall/LegacyListenerTrait.php index 260cb680e0ba..6f2bc2236356 100644 --- a/src/Symfony/Component/Security/Http/Firewall/LegacyListenerTrait.php +++ b/src/Symfony/Component/Security/Http/Firewall/LegacyListenerTrait.php @@ -15,6 +15,9 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; +// Help opcache.preload discover always-needed symbols +class_exists(RequestEvent::class); + /** * @deprecated * diff --git a/src/Symfony/Component/Stopwatch/Stopwatch.php b/src/Symfony/Component/Stopwatch/Stopwatch.php index a9f8862f523f..12c25f0aa4a4 100644 --- a/src/Symfony/Component/Stopwatch/Stopwatch.php +++ b/src/Symfony/Component/Stopwatch/Stopwatch.php @@ -13,6 +13,9 @@ use Symfony\Contracts\Service\ResetInterface; +// Help opcache.preload discover always-needed symbols +class_exists(Section::class); + /** * Stopwatch provides a way to profile code. * diff --git a/src/Symfony/Component/Translation/Formatter/MessageFormatter.php b/src/Symfony/Component/Translation/Formatter/MessageFormatter.php index a0ebde842b64..a16764069f8c 100644 --- a/src/Symfony/Component/Translation/Formatter/MessageFormatter.php +++ b/src/Symfony/Component/Translation/Formatter/MessageFormatter.php @@ -16,6 +16,9 @@ use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface; +// Help opcache.preload discover always-needed symbols +class_exists(IntlFormatter::class); + /** * @author Abdellatif Ait boudad */ diff --git a/src/Symfony/Component/Validator/ValidatorBuilder.php b/src/Symfony/Component/Validator/ValidatorBuilder.php index 42fcdc0fc101..808fbc7f43d0 100644 --- a/src/Symfony/Component/Validator/ValidatorBuilder.php +++ b/src/Symfony/Component/Validator/ValidatorBuilder.php @@ -35,6 +35,11 @@ use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorTrait; +// Help opcache.preload discover always-needed symbols +class_exists(TranslatorInterface::class); +class_exists(LocaleAwareInterface::class); +class_exists(TranslatorTrait::class); + /** * The default implementation of {@link ValidatorBuilderInterface}. * diff --git a/src/Symfony/Component/WebLink/EventListener/AddLinkHeaderListener.php b/src/Symfony/Component/WebLink/EventListener/AddLinkHeaderListener.php index 3027529a8455..25faf15bebc5 100644 --- a/src/Symfony/Component/WebLink/EventListener/AddLinkHeaderListener.php +++ b/src/Symfony/Component/WebLink/EventListener/AddLinkHeaderListener.php @@ -17,6 +17,9 @@ use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\WebLink\HttpHeaderSerializer; +// Help opcache.preload discover always-needed symbols +class_exists(HttpHeaderSerializer::class); + /** * Adds the Link HTTP header to the response. * diff --git a/src/Symfony/Contracts/Cache/CacheTrait.php b/src/Symfony/Contracts/Cache/CacheTrait.php index eda3d4931a15..1cc3841e2ac4 100644 --- a/src/Symfony/Contracts/Cache/CacheTrait.php +++ b/src/Symfony/Contracts/Cache/CacheTrait.php @@ -15,6 +15,9 @@ use Psr\Cache\InvalidArgumentException; use Psr\Log\LoggerInterface; +// Help opcache.preload discover always-needed symbols +class_exists(InvalidArgumentException::class); + /** * An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes. * diff --git a/src/Symfony/Contracts/Service/ServiceLocatorTrait.php b/src/Symfony/Contracts/Service/ServiceLocatorTrait.php index 4ec6eb4276cf..0b4d60affa5e 100644 --- a/src/Symfony/Contracts/Service/ServiceLocatorTrait.php +++ b/src/Symfony/Contracts/Service/ServiceLocatorTrait.php @@ -14,6 +14,10 @@ use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; +// Help opcache.preload discover always-needed symbols +class_exists(ContainerExceptionInterface::class); +class_exists(NotFoundExceptionInterface::class); + /** * A trait to help implement ServiceProviderInterface. *