@ The answer to my question is the simplest solution to such a question. However, the question of how to configure a resolver controller arises so often. Some time ago, I came across a redefinition of the framework service, so I decided to move on to the steps in Symfony 3.2.
The goal is to define a route, for example:
// routing.yml app.home_page: path: /test defaults: {_controller: AppBundle:UserInterface\Controller:Default:indexAction}
Note that there are four in _controller :. The idea is that the second argument will be used to determine the controller directory inside this package.
To implement this, we need to redefine the standard controller ControllerNameParser. When searching through FrameworkBundle \ Resources \ config, we find that the service is defined in web.xml with the identifier controller_name_converter. Returning to the good days, all framework classes had associated parameter values. We could actually change the service by simply adding a new parameter value for the class name. Currently, we need to change the actual service definition for which we need a compiler pass. Wiring:
// AppBundle.php namespace AppBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use AppBundle\DependencyInjection\Compiler\CustomPass; class AppBundle extends Bundle { // http://symfony.com/doc/current/service_container/compiler_passes.html public function build(ContainerBuilder $container) { parent::build($container); $container->addCompilerPass(new CustomPass()); } } // CustomPass.php namespace AppBundle\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; // http://symfony.com/doc/current/bundles/override.html#services-configuration class CustomPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { $definition = $container->getDefinition('controller_name_converter'); $definition->setClass('AppBundle\Controller\ControllerNameParser'); $definition->addArgument('SomeParameter'); } }
Note that I added an extra argument to the name parser to show how this can be done. Therefore, you can use some parameter values to indicate where to look for controllers.
The actual implementation of the custom name parser is a bit messy, mainly due to the nature of the task. It could be clarified, but basically any strings of controllers with four colons are processed.
namespace AppBundle\Controller; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser as ControllerNameParserBase; class ControllerNameParser extends ControllerNameParserBase { public function __construct(KernelInterface $kernel, $someParameter) { return parent::__construct($kernel); } public function parse($controllerString) { $parts = explode(':', $controllerString); if (4 !== count($parts)) { return parent::parse($controllerString); } list($bundleName, $controllerDir, $controller, $action) = $parts; $controller = str_replace('/', '\\', $controller); $bundle = $this->kernel->getBundle($bundleName, false)[0]; $try = $bundle->getNamespace().'\\'.$controllerDir.'\\'.$controller.'Controller'; if (class_exists($try)) { return $try.'::'.$action; } return parent::parse($controllerString); } }
So, although there are simpler ways to answer this specific question, if you really need to customize the way the resolver works, this answer may perhaps serve as a reference.