Last active
April 19, 2025 16:10
-
-
Save fritzmg/77755f3dfbe6366ae047295cc48a7a9f to your computer and use it in GitHub Desktop.
There is a curious circular dependency issue in Contao 4.13 when you try to decorate (or override) the `router` with your own `ChainRouter`. The first built container example shows the `getRouterService()` method without the decoration, the second with.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Here we have | |
* $this->services['router'] = $instance = new \Symfony\Cmf\Component\Routing\ChainRouter($a); | |
* almost right at the start, defining the `router` service very early. | |
*/ | |
protected function getRouterService() | |
{ | |
$a = ($this->privates['monolog.logger'] ?? $this->getMonolog_LoggerService()); | |
$this->services['router'] = $instance = new \Symfony\Cmf\Component\Routing\ChainRouter($a); | |
$b = ($this->privates['router.request_context'] ?? $this->getRouter_RequestContextService()); | |
$c = new \Symfony\Bridge\Monolog\Logger('router'); | |
$c->pushProcessor(($this->privates['contao.monolog.processor'] ?? $this->getContao_Monolog_ProcessorService())); | |
$c->pushHandler(($this->privates['monolog.handler.console'] ?? $this->getMonolog_Handler_ConsoleService())); | |
$c->pushHandler(($this->privates['monolog.handler.main'] ?? $this->getMonolog_Handler_MainService())); | |
$c->pushHandler(($this->privates['contao.monolog.handler'] ?? $this->getContao_Monolog_HandlerService())); | |
$d = new \Symfony\Bundle\FrameworkBundle\Routing\Router((new \Symfony\Component\DependencyInjection\Argument\ServiceLocator($this->getService, [ | |
'routing.loader' => ['services', 'routing.loader', 'getRouting_LoaderService', true], | |
], [ | |
'routing.loader' => 'Symfony\\Component\\Config\\Loader\\LoaderInterface', | |
]))->withContext('router.default', $this), 'contao_manager.routing.route_loader::loadFromPlugins', ['cache_dir' => $this->targetDir.'', 'debug' => false, 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator', 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\CompiledUrlGeneratorDumper', 'matcher_class' => 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher', 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherDumper', 'strict_requirements' => false, 'resource_type' => 'service'], $b, ($this->privates['parameter_bag'] ?? ($this->privates['parameter_bag'] = new \Symfony\Component\DependencyInjection\ParameterBag\ContainerBag($this))), $c, 'en'); | |
$d->setConfigCacheFactory(($this->privates['config_cache_factory'] ?? ($this->privates['config_cache_factory'] = new \Symfony\Component\Config\ResourceCheckerConfigCacheFactory()))); | |
$d->addExpressionLanguageProvider(($this->privates['router.expression_language_provider'] ?? $this->getRouter_ExpressionLanguageProviderService())); | |
$e = ($this->privates['contao.routing.route_provider'] ?? $this->getContao_Routing_RouteProviderService()); | |
$f = new \Contao\CoreBundle\Routing\PageUrlGenerator($e, ($this->services['contao.routing.page_registry'] ?? $this->getContao_Routing_PageRegistryService()), $a); | |
$g = ($this->services['event_dispatcher'] ?? $this->getEventDispatcherService()); | |
$h = new \Symfony\Cmf\Component\Routing\DynamicRouter($b, ($this->services['contao.routing.nested_matcher'] ?? $this->getContao_Routing_NestedMatcherService()), $f, '', $g, $e); | |
$h->addRouteEnhancer(new \Contao\CoreBundle\Routing\Enhancer\InputEnhancer(($this->services['contao.framework'] ?? $this->getContao_FrameworkService())), 0); | |
$instance->setContext($b); | |
$instance->add($d, '100'); | |
$instance->add(new \Symfony\Cmf\Component\Routing\DynamicRouter($b, ($this->services['contao.routing.nested_404_matcher'] ?? $this->getContao_Routing_Nested404MatcherService()), $f, '', $g, ($this->privates['contao.routing.route_404_provider'] ?? $this->getContao_Routing_Route404ProviderService())), -200); | |
$instance->add($h, 20); | |
return $instance; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Here we have | |
* $this->services['router'] = $instance = new \App\Routing\ChainRouter($h); | |
* much later, which causes a recursion between `@contao.framework` and `@contao.routing.route_provider`. | |
* `@contao.framework` tries to get the `@router`, `getRouterService()` tries to get `@contao.routing.route_provider` | |
* wich then tries to get `@contao.framework`, which then tries to get the `@router` etc. | |
*/ | |
protected function getRouterService() | |
{ | |
$a = ($this->privates['contao.routing.route_provider'] ?? $this->getContao_Routing_RouteProviderService()); | |
if (isset($this->services['router'])) { | |
return $this->services['router']; | |
} | |
$b = ($this->services['contao.routing.page_registry'] ?? $this->getContao_Routing_PageRegistryService()); | |
if (isset($this->services['router'])) { | |
return $this->services['router']; | |
} | |
$c = ($this->services['event_dispatcher'] ?? $this->getEventDispatcherService()); | |
if (isset($this->services['router'])) { | |
return $this->services['router']; | |
} | |
$d = ($this->privates['contao.routing.route_404_provider'] ?? $this->getContao_Routing_Route404ProviderService()); | |
if (isset($this->services['router'])) { | |
return $this->services['router']; | |
} | |
$e = ($this->services['contao.routing.nested_matcher'] ?? $this->getContao_Routing_NestedMatcherService()); | |
if (isset($this->services['router'])) { | |
return $this->services['router']; | |
} | |
$f = ($this->services['contao.framework'] ?? $this->getContao_FrameworkService()); | |
if (isset($this->services['router'])) { | |
return $this->services['router']; | |
} | |
$g = ($this->privates['monolog.logger'] ?? $this->getMonolog_LoggerService()); | |
$h = new \Symfony\Cmf\Component\Routing\ChainRouter($g); | |
$i = ($this->privates['router.request_context'] ?? $this->getRouter_RequestContextService()); | |
$j = new \Symfony\Bridge\Monolog\Logger('router'); | |
$j->pushProcessor(($this->privates['contao.monolog.processor'] ?? $this->getContao_Monolog_ProcessorService())); | |
$j->pushHandler(($this->privates['monolog.handler.console'] ?? $this->getMonolog_Handler_ConsoleService())); | |
$j->pushHandler(($this->privates['monolog.handler.main'] ?? $this->getMonolog_Handler_MainService())); | |
$j->pushHandler(($this->privates['contao.monolog.handler'] ?? $this->getContao_Monolog_HandlerService())); | |
$k = new \Symfony\Bundle\FrameworkBundle\Routing\Router((new \Symfony\Component\DependencyInjection\Argument\ServiceLocator($this->getService, [ | |
'routing.loader' => ['services', 'routing.loader', 'getRouting_LoaderService', true], | |
], [ | |
'routing.loader' => 'Symfony\\Component\\Config\\Loader\\LoaderInterface', | |
]))->withContext('router.default', $this), 'contao_manager.routing.route_loader::loadFromPlugins', ['cache_dir' => $this->targetDir.'', 'debug' => false, 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\CompiledUrlGenerator', 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\CompiledUrlGeneratorDumper', 'matcher_class' => 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableCompiledUrlMatcher', 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\CompiledUrlMatcherDumper', 'strict_requirements' => false, 'resource_type' => 'service'], $i, ($this->privates['parameter_bag'] ?? ($this->privates['parameter_bag'] = new \Symfony\Component\DependencyInjection\ParameterBag\ContainerBag($this))), $j, 'en'); | |
$k->setConfigCacheFactory(($this->privates['config_cache_factory'] ?? ($this->privates['config_cache_factory'] = new \Symfony\Component\Config\ResourceCheckerConfigCacheFactory()))); | |
$k->addExpressionLanguageProvider(($this->privates['router.expression_language_provider'] ?? $this->getRouter_ExpressionLanguageProviderService())); | |
$this->services['router'] = $instance = new \App\Routing\ChainRouter($h); | |
$l = new \Contao\CoreBundle\Routing\PageUrlGenerator($a, $b, $g); | |
$m = new \Symfony\Cmf\Component\Routing\DynamicRouter($i, $e, $l, '', $c, $a); | |
$m->addRouteEnhancer(new \Contao\CoreBundle\Routing\Enhancer\InputEnhancer($f), 0); | |
$h->setContext($i); | |
$h->add($k, '100'); | |
$h->add(new \Symfony\Cmf\Component\Routing\DynamicRouter($i, ($this->services['contao.routing.nested_404_matcher'] ?? $this->getContao_Routing_Nested404MatcherService()), $l, '', $c, $d), -200); | |
$h->add($m, 20); | |
return $instance; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Routing; | |
use Symfony\Cmf\Component\Routing\ChainRouterInterface; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; | |
use Symfony\Component\Routing\RequestContext; | |
class ChainRouter implements ChainRouterInterface, WarmableInterface | |
{ | |
public function __construct(private readonly ChainRouterInterface&WarmableInterface $inner) | |
{ | |
} | |
public function add($router, $priority = 0): void | |
{ | |
$this->inner->add($router, $priority); | |
} | |
public function all() | |
{ | |
return $this->inner->all(); | |
} | |
public function warmUp(string $cacheDir, string|null $buildDir = null): void | |
{ | |
$this->inner->warmUp($cacheDir); | |
} | |
public function getRouteCollection() | |
{ | |
return $this->inner->getRouteCollection(); | |
} | |
public function match(string $pathinfo) | |
{ | |
return $this->inner->match($pathinfo); | |
} | |
public function matchRequest(Request $request) | |
{ | |
return $this->inner->matchRequest($request); | |
} | |
public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string | |
{ | |
return $this->inner->generate($name, $parameters, $referenceType); | |
} | |
public function setContext(RequestContext $context): void | |
{ | |
$this->inner->setContext($context); | |
} | |
public function getContext(): RequestContext | |
{ | |
return $this->inner->getContext(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
services: | |
App\ChainRouter: | |
decorates: cmf_routing.router | |
arguments: ['@.inner'] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment