diff --git a/UPGRADE-4.4.md b/UPGRADE-4.4.md
index c3b9ad8688616..def83c08676c3 100644
--- a/UPGRADE-4.4.md
+++ b/UPGRADE-4.4.md
@@ -94,6 +94,7 @@ FrameworkBundle
* The `ControllerResolver` and `DelegatingLoader` classes have been marked as `final`.
* The `controller_name_converter` and `resolve_controller_name_subscriber` services have been deprecated.
* Deprecated `routing.loader.service`, use `routing.loader.container` instead.
+ * Not tagging service route loaders with `routing.route_loader` has been deprecated.
HttpClient
----------
diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md
index 284e942c9aec3..461c90e51c4e6 100644
--- a/UPGRADE-5.0.md
+++ b/UPGRADE-5.0.md
@@ -373,6 +373,7 @@ Routing
Instead of overwriting them, use `__serialize` and `__unserialize` as extension points which are forward compatible
with the new serialization methods in PHP 7.4.
* Removed `ServiceRouterLoader` and `ObjectRouteLoader`.
+ * Service route loaders must be tagged with `routing.route_loader`.
Security
--------
diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
index 607766850a03e..f2c575a56ece6 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -11,6 +11,7 @@ CHANGELOG
* Added support for configuring chained cache pools
* Deprecated booting the kernel before running `WebTestCase::createClient()`
* Deprecated `routing.loader.service`, use `routing.loader.container` instead.
+ * Not tagging service route loaders with `routing.route_loader` has been deprecated.
4.3.0
-----
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
index efeafad5f06e0..00fc826cf2096 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.route_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 cb9eaeaf3d3b3..8d3555f441f8f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -24,6 +24,7 @@
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader;
use Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher;
+use Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface;
use Symfony\Bundle\FullStack;
use Symfony\Component\Asset\PackageInterface;
use Symfony\Component\BrowserKit\AbstractBrowser;
@@ -446,6 +447,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(RouteLoaderInterface::class)
+ ->addTag('routing.route_loader');
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php
index 3919737e44dac..c228734725af8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php
@@ -69,14 +69,20 @@ 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.route_loader');
+
+ 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 21530280d3f07..b85e9fa71d1cc 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
@@ -47,7 +47,12 @@
-
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/LegacyRouteLoaderContainer.php b/src/Symfony/Bundle/FrameworkBundle/Routing/LegacyRouteLoaderContainer.php
new file mode 100644
index 0000000000000..fa110ddb5dd0b
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Routing/LegacyRouteLoaderContainer.php
@@ -0,0 +1,51 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Routing;
+
+use Psr\Container\ContainerInterface;
+
+/**
+ * @internal to be removed in Symfony 5.0
+ */
+class LegacyRouteLoaderContainer 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 service route loader "%s" without tagging it with the "routing.route_loader" tag is deprecated since Symfony 4.4 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/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php b/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.php
new file mode 100644
index 0000000000000..d1cb55a7af895
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Routing/RouteLoaderInterface.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\Bundle\FrameworkBundle\Routing;
+
+/**
+ * Marker interface for service route loaders.
+ */
+interface RouteLoaderInterface
+{
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php
index 539306fcea2b9..dd909ea6fc8ce 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,18 @@ 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.route_loader'));
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/LegacyRouteLoaderContainerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/LegacyRouteLoaderContainerTest.php
new file mode 100644
index 0000000000000..cd002453baa31
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/LegacyRouteLoaderContainerTest.php
@@ -0,0 +1,68 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Routing;
+
+use PHPUnit\Framework\TestCase;
+use Psr\Container\ContainerInterface;
+use Symfony\Bundle\FrameworkBundle\Routing\LegacyRouteLoaderContainer;
+use Symfony\Component\DependencyInjection\Container;
+
+/**
+ * @group legacy
+ */
+class LegacyRouteLoaderContainerTest extends TestCase
+{
+ /**
+ * @var ContainerInterface
+ */
+ private $container;
+
+ /**
+ * @var ContainerInterface
+ */
+ private $serviceLocator;
+
+ /**
+ * @var LegacyRouteLoaderContainer
+ */
+ private $legacyRouteLoaderContainer;
+
+ /**
+ * {@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->legacyRouteLoaderContainer = new LegacyRouteLoaderContainer($this->container, $this->serviceLocator);
+ }
+
+ /**
+ * @expectedDeprecation Registering the service route loader "foo" without tagging it with the "routing.route_loader" tag is deprecated since Symfony 4.4 and will be required in Symfony 5.0.
+ */
+ public function testGet()
+ {
+ $this->assertSame($this->container->get('foo'), $this->legacyRouteLoaderContainer->get('foo'));
+ $this->assertSame($this->serviceLocator->get('bar'), $this->legacyRouteLoaderContainer->get('bar'));
+ }
+
+ public function testHas()
+ {
+ $this->assertTrue($this->legacyRouteLoaderContainer->has('foo'));
+ $this->assertTrue($this->legacyRouteLoaderContainer->has('bar'));
+ $this->assertFalse($this->legacyRouteLoaderContainer->has('ccc'));
+ }
+}