diff --git a/UPGRADE-4.3.md b/UPGRADE-4.3.md
index 3f5f22164dfaa..60640d5b2168c 100644
--- a/UPGRADE-4.3.md
+++ b/UPGRADE-4.3.md
@@ -123,6 +123,7 @@ Routing
options have been deprecated.
* Implementing `Serializable` for `Route` and `CompiledRoute` is deprecated; if you serialize them, please
ensure your unserialization logic can recover from a failure related to an updated serialization format
+ * Not tagging the router loader services with `routing.router_loader` has been deprecated.
Security
--------
diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md
index f0ba1c429bdcf..adcb91389fc51 100644
--- a/UPGRADE-5.0.md
+++ b/UPGRADE-5.0.md
@@ -284,6 +284,7 @@ Routing
options have been removed.
* `Route` and `CompiledRoute` don't implement `Serializable` anymore; if you serialize them, please
ensure your unserialization logic can recover from a failure related to an updated serialization format
+ * The router loader services must be tagged with `routing.router_loader`.
Security
--------
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
index efeafad5f06e0..c90b5215eda33 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
@@ -49,6 +49,7 @@ class UnusedTagsPass implements CompilerPassInterface
'proxy',
'routing.expression_language_provider',
'routing.loader',
+ 'routing.router_loader',
'security.expression_language_provider',
'security.remember_me_aware',
'security.voter',
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 3413eb2b13310..c81f3465653b8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -92,6 +92,7 @@
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
+use Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoaderInterface;
use Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
use Symfony\Component\Security\Core\Security;
@@ -428,6 +429,9 @@ public function load(array $configs, ContainerBuilder $container)
if (!$config['disallow_search_engine_index'] ?? false) {
$container->removeDefinition('disallow_search_engine_index_response_listener');
}
+
+ $container->registerForAutoconfiguration(ServiceRouterLoaderInterface::class)
+ ->addTag('routing.router_loader');
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php
index 3919737e44dac..5af6053966d4a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php
@@ -69,14 +69,23 @@ public function registerContainerConfiguration(LoaderInterface $loader)
],
]);
- if ($this instanceof EventSubscriberInterface) {
+ if (!$container->hasDefinition('kernel')) {
$container->register('kernel', static::class)
->setSynthetic(true)
->setPublic(true)
- ->addTag('kernel.event_subscriber')
;
}
+ $kernelDefinition = $container->getDefinition('kernel');
+
+ $kernelDefinition->addTag('routing.router_loader', [
+ 'service_id' => 'kernel',
+ ]);
+
+ if ($this instanceof EventSubscriberInterface) {
+ $kernelDefinition->addTag('kernel.event_subscriber');
+ }
+
$this->configureContainer($container, $loader);
$container->addObjectResource($this);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
index 8c293ebefc390..38af911cdf42a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
@@ -40,9 +40,14 @@
+
+
+
+
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php
index 539306fcea2b9..201316b37256f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php
@@ -12,6 +12,9 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Kernel;
use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
+use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\HttpFoundation\Request;
class MicroKernelTraitTest extends TestCase
@@ -39,4 +42,21 @@ public function testAsEventSubscriber()
$this->assertSame('It\'s dangerous to go alone. Take this ⚔', $response->getContent());
}
+
+ public function testRoutingRouteLoaderTagIsAdded()
+ {
+ $frameworkExtension = $this->createMock(ExtensionInterface::class);
+ $frameworkExtension
+ ->expects($this->atLeastOnce())
+ ->method('getAlias')
+ ->willReturn('framework');
+
+ $container = new ContainerBuilder();
+ $container->registerExtension($frameworkExtension);
+
+ $kernel = new ConcreteMicroKernel('test', false);
+ $kernel->registerContainerConfiguration(new ClosureLoader($container));
+
+ $this->assertTrue($container->getDefinition('kernel')->hasTag('routing.router_loader'));
+ }
}
diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md
index f7439903e04a5..fd39033788d57 100644
--- a/src/Symfony/Component/Routing/CHANGELOG.md
+++ b/src/Symfony/Component/Routing/CHANGELOG.md
@@ -11,7 +11,7 @@ CHANGELOG
* deprecated implementing `Serializable` for `Route` and `CompiledRoute`; if you serialize them, please
ensure your unserialization logic can recover from a failure related to an updated serialization format
* exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators
- * added support for invokable route loader services
+ * added support for invokable router loader services
4.2.0
-----
diff --git a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderContainer.php b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderContainer.php
new file mode 100644
index 0000000000000..c6ec0eace0475
--- /dev/null
+++ b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderContainer.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Loader\DependencyInjection;
+
+use Psr\Container\ContainerInterface;
+
+/**
+ * @internal
+ *
+ * @deprecated since Symfony 4.3, to be removed in 5.0
+ */
+class ServiceRouterLoaderContainer implements ContainerInterface
+{
+ private $container;
+ private $serviceLocator;
+
+ public function __construct(ContainerInterface $container, ContainerInterface $serviceLocator)
+ {
+ $this->container = $container;
+ $this->serviceLocator = $serviceLocator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($id)
+ {
+ if ($this->serviceLocator->has($id)) {
+ return $this->serviceLocator->get($id);
+ }
+
+ @trigger_error(sprintf('Registering the routing loader "%s" without tagging it with the "routing.router_loader" tag is deprecated since Symfony 4.3 and will be required in Symfony 5.0.', $id), E_USER_DEPRECATED);
+
+ return $this->container->get($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($id)
+ {
+ return $this->serviceLocator->has($id) || $this->container->has($id);
+ }
+}
diff --git a/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderInterface.php b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderInterface.php
new file mode 100644
index 0000000000000..e77d691b6f78c
--- /dev/null
+++ b/src/Symfony/Component/Routing/Loader/DependencyInjection/ServiceRouterLoaderInterface.php
@@ -0,0 +1,19 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Loader\DependencyInjection;
+
+/**
+ * Marker interface for router loader services.
+ */
+interface ServiceRouterLoaderInterface
+{
+}
diff --git a/src/Symfony/Component/Routing/Tests/Loader/DependencyInjection/ServiceRouterLoaderContainerTest.php b/src/Symfony/Component/Routing/Tests/Loader/DependencyInjection/ServiceRouterLoaderContainerTest.php
new file mode 100644
index 0000000000000..1e97555161ef6
--- /dev/null
+++ b/src/Symfony/Component/Routing/Tests/Loader/DependencyInjection/ServiceRouterLoaderContainerTest.php
@@ -0,0 +1,66 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Tests\Loader;
+
+use PHPUnit\Framework\TestCase;
+use Psr\Container\ContainerInterface;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\Routing\Loader\DependencyInjection\ServiceRouterLoaderContainer;
+
+class ServiceRouterLoaderContainerTest extends TestCase
+{
+ /**
+ * @var ContainerInterface
+ */
+ private $container;
+
+ /**
+ * @var ContainerInterface
+ */
+ private $serviceLocator;
+
+ /**
+ * @var ServiceRouterLoaderContainer
+ */
+ private $serviceRouterLoaderContainer;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp()
+ {
+ $this->container = new Container();
+ $this->container->set('foo', new \stdClass());
+
+ $this->serviceLocator = new Container();
+ $this->serviceLocator->set('bar', new \stdClass());
+
+ $this->serviceRouterLoaderContainer = new ServiceRouterLoaderContainer($this->container, $this->serviceLocator);
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation Registering the routing loader "foo" without tagging it with the "routing.router_loader" tag is deprecated since Symfony 4.3 and will be required in Symfony 5.0.
+ */
+ public function testGet()
+ {
+ $this->assertSame($this->container->get('foo'), $this->serviceRouterLoaderContainer->get('foo'));
+ $this->assertSame($this->serviceLocator->get('bar'), $this->serviceRouterLoaderContainer->get('bar'));
+ }
+
+ public function testHas()
+ {
+ $this->assertTrue($this->serviceRouterLoaderContainer->has('foo'));
+ $this->assertTrue($this->serviceRouterLoaderContainer->has('bar'));
+ $this->assertFalse($this->serviceRouterLoaderContainer->has('ccc'));
+ }
+}