Автопроводка 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');
// ...
}