Изменить папку контроллеров Symfony 3

Я работаю над проектом с Symfony 3, и я хочу, чтобы моя папка AppBundle была такой:

  • AppBundle/
    • домен/
    • приложения/
    • инфраструктуре/
    • UserInterface/

    2 ответов


    вы также можете обратиться к этому контроллеру, используя его полное имя класса и метода (Ref.):

    app.home_page:
        path: /test
        defaults: { _controller: AppBundle\UserInterface\Controller\DefaultController::indexA‌​ction }
    

    @Yonel действительно самым простым решением в такого рода вопросе. Однако вопрос о том, как настроить контроллер-резольвер, возникает так часто. Прошло некоторое время с тех пор, как я возился с переопределением фреймворка, поэтому я решил пройти шаги в Symfony 3.2.

    цель состоит в том, чтобы иметь возможность определить маршрут, как:

    // routing.yml
    app.home_page:
      path: /test
      defaults: {_controller: AppBundle:UserInterface\Controller:Default:indexAction}
    

    обратите внимание, что в _controller есть четыре:. Идея заключается в том, что второй аргумент будет использоваться для определения каталог контроллера внутри данного пакета.

    чтобы реализовать это, нам нужно переопределить ControllerNameParser по умолчанию. Поиск через FrameworkBundle\Resources\config мы находим, что служба определена в интернете.xml с идентификатором controller_name_converter. В хорошие дни ole все классы framework имели связанные значения параметров. Мы могли бы фактически изменить службу, просто указав новое значение параметра для имени класса. В наше время, нам нужно доработать фактическое определение службы, для которого нам нужен пропуск компилятора. Проводка:

    // 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');
        }
    }
    

    обратите внимание, что я добавил дополнительный аргумент в парсер имен, чтобы показать, как это можно сделать. Таким образом, вы можете использовать некоторые значения параметров, чтобы указать, где искать контроллеры.

    фактическая реализация пользовательского парсера имен немного запутана в основном из-за характера задачи. Это, безусловно, может быть уточнено, но в основном любые строки контроллера с четырьмя двоеточия обрабатываются.

    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);
        }
    }
    

    таким образом, хотя есть более простые способы ответить на этот конкретный вопрос, если вам действительно нужно настроить, как работает решатель, то этот ответ, возможно, может служить ссылкой.