Автопроводка Symfony для Legacy-контроллеров без PSR-4

У меня есть старое приложение, и я использую Symfony с ним. Пока все отлично работает.

Теперь я хочу использовать Autowiring для своих Legacy-контроллеров.

  • они загружаются с помощью композиторов classmap функциональность
  • находятся в пространстве корневых имен (например, \Controller_Page)
  • имена классов отличаются от имен файлов

Да уж. Я знаю, что это дерьмо. Но это наследие, и я не хочу касаться каждого контроллера в данный момент (большие проблемы в этом приложении).

Я хотел бы использовать Dependency-Injection и Autowiring, чтобы уменьшить (ужасный) беспорядок.

Вот несколько подходов, которые я уже попробовал:

services:
 _defaults:
        autowire: true
        autoconfigure: true
    "\\":
        resource: '../legacy/Controller'
        tags: ['controller.service_arguments']

Пространство имен не является действительным префиксом PSR-4

services:
 _defaults:
        autowire: true
        autoconfigure: true
    "":
        resource: '../legacy/Controller'
        tags: ['controller.service_arguments']

Префикс пространства имен должен заканчиваться на "\"

// in Kernel::configureContainer()
$container->registerForAutoconfiguration(\BaseController::class);

(мой \BaseController имеет только Symfony\Component\HttpFoundation\RequestStack как __construct-argument)

Контроллер "BaseController" имеет обязательные аргументы конструктора и не существует в контейнере. Вы забыли определить такой сервис?

// in Kernel::configureContainer()
$container->registerForAutoconfiguration(\Controller_Legacy::class);

Не удается загрузить ресурс "4208ad7faaf7d383f981bd32e92c4f2f".

Я понятия не имею, как этого добиться. Спасибо за вашу помощь.

Редактировать 1

Получил еще один шаг вперед. Я выполнил автоконфигурацию для одного из этих устаревших контроллеров, например:

// Kernel.php
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
{
    $container->addDefinitions([
        \Controller_Legacy::class => (new Definition(\Controller_Legacy::class))
            ->setAutowired(true)
            ->setAutoconfigured(true)
            ->addTag('controller.service_arguments'),
    ]);


    // ...
}

Таким образом, кажется, что мои предыдущие проблемы были вызваны конфигурацией yaml или чем-то, а не самим контейнером.

Теперь мне нужно найти способ зарегистрировать все мои Legacy-контроллеры. Поиграюсь немного и обновлю, если найду хорошее решение. (Хорошие решения более чем приветствуются)

Edit2

Хорошо, это была не YAML-конфигурация. Если я использую PHP-конфигурацию, я получаю ту же проблему.

/** @var $this \Symfony\Component\DependencyInjection\Loader\PhpFileLoader */

$definition = new Definition();

$definition
    ->setAutowired(true)
    ->setAutoconfigured(true)
    ->setPublic(false)
;

$this->registerClasses($definition, '\\', '../legacy/*');

Пространство имен не является действительным префиксом PSR-4.

Я сейчас попробую зарегистрировать классы вручную.

1 ответ

Решение

Хорошо, я добавил шаг, который приводит к этому результату в исходном вопросе. Для меня это решение работает. Возможно, не самый лучший, но делает свое дело. (Откройте для лучших предложений, хотя).

В Kernel.php Я злоупотребил composer-Autoloader, чтобы получить нужные мне классы, и зарегистрировал их как Services. Поскольку неиспользуемые Сервисы будут удалены, у меня нет проблем:-)

protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
{
    /** @var ClassLoader $classLoader */
    $classLoader = require $this->getProjectDir().'/vendor/autoload.php';

    foreach (array_keys($classLoader->getClassMap()) as $class) {
        $definition = (new Definition($class))
            ->setAutowired(true)
            ->setAutoconfigured(true)
            ->setPublic(false);

        $container->setDefinition($class, $definition);
    }

    // Since my ClassMap contains not only controllers, I add the 'controller.service_arguments'-Tag
    // after the loop.
    $container
        ->registerForAutoconfiguration(\BaseController::class)
        ->addTag('controller.service_arguments');

    // ...
}
Другие вопросы по тегам