From d78b50bc1108f4519105026c69315df65eea91f7 Mon Sep 17 00:00:00 2001 From: Danny van Wijk Date: Thu, 11 Sep 2025 14:15:26 +0200 Subject: [PATCH] Improve performance for LiveUrlSubscriber --- .../LiveComponentExtension.php | 9 ++-- .../src/EventListener/LiveUrlSubscriber.php | 47 ++++++++++++++----- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/LiveComponent/src/DependencyInjection/LiveComponentExtension.php b/src/LiveComponent/src/DependencyInjection/LiveComponentExtension.php index 6415526c528..91da00e4e20 100644 --- a/src/LiveComponent/src/DependencyInjection/LiveComponentExtension.php +++ b/src/LiveComponent/src/DependencyInjection/LiveComponentExtension.php @@ -24,6 +24,7 @@ use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Routing\RouterInterface; use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; use Symfony\UX\LiveComponent\ComponentValidator; use Symfony\UX\LiveComponent\ComponentValidatorInterface; @@ -138,12 +139,10 @@ function (ChildDefinition $definition, AsLiveComponent $attribute) { ; $container->register('ux.live_component.live_url_subscriber', LiveUrlSubscriber::class) - ->setArguments([ - new Reference('ux.live_component.metadata_factory'), - new Reference('ux.live_component.component_hydrator'), - new Reference('router'), - ]) ->addTag('kernel.event_subscriber') + ->addTag('container.service_subscriber', ['key' => LiveComponentHydrator::class, 'id' => 'ux.live_component.component_hydrator']) + ->addTag('container.service_subscriber', ['key' => LiveComponentMetadataFactory::class, 'id' => 'ux.live_component.metadata_factory']) + ->addTag('container.service_subscriber', ['key' => RouterInterface::class, 'id' => 'router']) ; $container->register('ux.live_component.live_responder', LiveResponder::class); diff --git a/src/LiveComponent/src/EventListener/LiveUrlSubscriber.php b/src/LiveComponent/src/EventListener/LiveUrlSubscriber.php index 1bcb79a9cf7..a7d719baea9 100644 --- a/src/LiveComponent/src/EventListener/LiveUrlSubscriber.php +++ b/src/LiveComponent/src/EventListener/LiveUrlSubscriber.php @@ -11,11 +11,13 @@ namespace Symfony\UX\LiveComponent\EventListener; +use Psr\Container\ContainerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\RouterInterface; +use Symfony\Contracts\Service\ServiceSubscriberInterface; use Symfony\UX\LiveComponent\LiveComponentHydrator; use Symfony\UX\LiveComponent\Metadata\LiveComponentMetadataFactory; use Symfony\UX\TwigComponent\MountedComponent; @@ -23,17 +25,24 @@ /** * @internal */ -class LiveUrlSubscriber implements EventSubscriberInterface +class LiveUrlSubscriber implements EventSubscriberInterface, ServiceSubscriberInterface { private const URL_HEADER = 'X-Live-Url'; public function __construct( - private LiveComponentMetadataFactory $metadataFactory, - private LiveComponentHydrator $liveComponentHydrator, - private RouterInterface $router, + private ContainerInterface $container, ) { } + public static function getSubscribedServices(): array + { + return [ + LiveComponentMetadataFactory::class, + LiveComponentHydrator::class, + RouterInterface::class, + ]; + } + public function onKernelResponse(ResponseEvent $event): void { $request = $event->getRequest(); @@ -68,10 +77,10 @@ private function extractUrlLiveProps(MountedComponent $mounted): array { $pathProps = $queryProps = []; - $mountedMetadata = $this->metadataFactory->getMetadata($mounted->getName()); + $mountedMetadata = $this->getMetadataFactory()->getMetadata($mounted->getName()); if ([] !== $urlMappings = $mountedMetadata->getAllUrlMappings($mounted->getComponent())) { - $dehydratedProps = $this->liveComponentHydrator->dehydrate($mounted->getComponent(), $mounted->getAttributes(), $mountedMetadata); + $dehydratedProps = $this->getLiveComponentHydrator()->dehydrate($mounted->getComponent(), $mounted->getAttributes(), $mountedMetadata); $props = $dehydratedProps->getProps(); foreach ($urlMappings as $name => $urlMapping) { @@ -95,14 +104,15 @@ private function generateNewLiveUrl(string $previousUrl, array $pathProps, array $newQueryString = $previousUrlParsed['query'] ?? ''; if ([] !== $pathProps) { - $context = $this->router->getContext(); + $router = $this->getRouter(); + $context = $router->getContext(); try { // Re-create a context for the URL rendering the current LiveComponent $tmpContext = clone $context; $tmpContext->setMethod('GET'); - $this->router->setContext($tmpContext); + $router->setContext($tmpContext); - $routeMatched = $this->router->match($previousUrlParsed['path']); + $routeMatched = $router->match($previousUrlParsed['path']); $routeParams = []; foreach ($routeMatched as $k => $v) { if ('_route' === $k || '_controller' === $k) { @@ -111,11 +121,11 @@ private function generateNewLiveUrl(string $previousUrl, array $pathProps, array $routeParams[$k] = \array_key_exists($k, $pathProps) ? $pathProps[$k] : $v; } - $newUrl = $this->router->generate($routeMatched['_route'], $routeParams); + $newUrl = $router->generate($routeMatched['_route'], $routeParams); } catch (ResourceNotFoundException) { // reuse the previous URL path } finally { - $this->router->setContext($context); + $router->setContext($context); } } @@ -131,4 +141,19 @@ private function generateNewLiveUrl(string $previousUrl, array $pathProps, array return $newUrl.($newQueryString ? '?'.$newQueryString : ''); } + + private function getMetadataFactory(): LiveComponentMetadataFactory + { + return $this->container->get(LiveComponentMetadataFactory::class); + } + + private function getLiveComponentHydrator(): LiveComponentHydrator + { + return $this->container->get(LiveComponentHydrator::class); + } + + private function getRouter(): RouterInterface + { + return $this->container->get(RouterInterface::class); + } }