Symfony 3: не удается получить доступ к контейнеру изнутри контроллера
Я переношу свое приложение с Symfony 2.8 на Symfony 3.3.
Изнутри моего контроллера у меня есть это:
public function indexAction()
{
$email = new Email();
$form = $this->createForm(GetStartedType::class, $email, [
'action' => $this->generateUrl('get_started_end'),
'method' => 'POST',
]);
return [
'form' => $form->createView(),
];
}
Но я получаю это исключение:
Вызов функции-члена get() при нулевом значении
Мой контроллер расширяется Symfony\Bundle\FrameworkBundle\Controller\Controller
:
/**
* {@inheritdoc}
*/
class DefaultController extends Controller
{
...
}
Так что у меня есть доступ к контейнеру.
Поместив несколько дампов в код Symfony, я вижу, что контейнер установлен правильно:
namespace Symfony\Component\DependencyInjection;
/**
* ContainerAware trait.
*
* @author Fabien Potencier <[email protected]>
*/
trait ContainerAwareTrait
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* Sets the container.
*
* @param ContainerInterface|null $container A ContainerInterface instance or null
*/
public function setContainer(ContainerInterface $container = null)
{
dump('Here in the ContainerAwareTrait');
dump(null === $container);
$this->container = $container;
}
}
Это свалки
Here in the ContainerAwareTrait
false
Таким образом, автопроводка работает хорошо и устанавливает контейнер.
Но в ControllerTrait
У меня есть это:
trait ControllerTrait
{
/**
* Generates a URL from the given parameters.
*
* @param string $route The name of the route
* @param mixed $parameters An array of parameters
* @param int $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
*
* @return string The generated URL
*
* @see UrlGeneratorInterface
*/
protected function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
{
dump('Here in the ControllerTrait');
die(dump(null === $this->container));
return $this->container->get('router')->generate($route, $parameters, $referenceType);
}
...
Это дамп:
Here in the ControllerTrait
true
Итак, здесь container
равно null
, и это вызывает ошибку.
Любой может помочь мне решить эту проблему?
Почему container
равно нулю?
Если может помочь, это конфигурация services.yml
(по умолчанию, которая используется с Symfony):
# controllers are imported separately to make sure they're public
# and have a tag that allows actions to type-hint services
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
Этот вопрос опубликован как проблема на трекере проблем Symfony.
2 answers
Возможность автоматического подключения S3.3 немного упрощает определение контроллеров как служб.
Обычная мотивация, лежащая в основе определения контроллеров как служб, заключается в том, чтобы избежать введения контейнера. Другими словами, вы должны явно вводить каждую службу, используемую контроллером. Возможность автоматического подключения позволяет вам использовать инъекцию метода действия, поэтому вам не нужно вводить кучу вещей в конструктор.
Однако базовый класс контроллера Symfony предоставляет ряд вспомогательная функция, которая использует около 12 различных сервисов. Было бы действительно больно вводить их по одному за раз. Я вроде как думал, что возможность автоматического подключения может позаботиться об этом для вас, но, думаю, нет.
Таким образом, вам в основном нужно добавить вызов setContainer в определение службы. Что-то вроде:
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
[[setContainer, ['@service_container']]]
tags: ['controller.service_arguments']
Возможность автоматического подключения находится в стадии разработки, поэтому я не удивлюсь, если это изменится для 3.4/4.0.
Эта проблема исправлена PR #23239 и переиздана в Symfony 3.3.3.