Метод getUser() не работает в конструкторе контроллеров
Я хочу получить пользовательский объект в конструкторе контроллеров в проекте Symfony 4.3.2. Согласно документам на https://symfony.com/doc/4.0/security.html, мне просто нужно вызвать $this->getUser(). И да, это работает в методах действия.
НО: попытка получить пользователя в конструкторе не работает, потому что контейнер НЕ будет инициализирован здесь, а метод getUser выдает исключение "Вызов функции-члена has() при нулевом значении": в этот момент контейнер является нулевым). во время.
Это работает:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class TestController extends AbstractController
{
public function indexAction()
{
dump($this->getUser());
}
}
Это не:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class TestController extends AbstractController
{
public function __contruct()
{
dump($this->getUser());
}
public function indexAction()
{
}
}
И когда я ввожу контейнер вручную, тогда все тоже хорошо:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class TestController extends AbstractController
{
public function __construct(ContainerInterface $container)
{
$this->container = $container;
dump($this->getUser());
}
public function indexAction()
{
}
}
Кстати, это метод getUser в AbstractController:
protected function getUser()
{
if (!$this->container->has('security.token_storage')) {
throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".');
}
......
Является ли это ошибкой, что контейнер не инициализируется в конструкторе, или это функция, которую вы должны инициализировать вручную, когда вам нужен пользователь в конструкторе?
Изменить: использование способа, показанного в https://symfony.com/blog/new-in-symfony-3-2-user-value-resolver-for-controllers, работает в действиях, но не работает в конструкторе:
....
private $user;
public function __construct(UserInterface $user)
{
$this->user = $user;
}
выдает следующее сообщение об ошибке: Cannot autowire service "App\Controller\TestController": argument "$user" of method "__construct()" references interface "Symfony\Component\Security\Core\User\UserInterface" but no such service exists. Did you create a class that implements this interface?
, И именно здесь я хотел бы установить объект пользователя.
2 ответа
Контейнер устанавливается ControllerResolver
после того, как контроллер был создан путем вызова setContainer
метод, который вы упоминаете. Таким образом, когда конструктор вызывается, контейнер недоступен по проекту.
Возможно, у вас есть сценарий использования, но я не понимаю, почему вы хотите это сделать, так как в ваших методах контроллера у вас будет доступ к $user
свойство, и это просто спасет вас, набрав get()
, Вы можете ввести весь контейнер, как показано в вашем образце, или вы можете ввести только Security
оказание услуг.
use Symfony\Component\Security\Core\Security;
class TestController extends AbstractController
{
private $user;
public function __construct(Security $security)
{
$this->user = $security->getUser();
}
public function indexAction()
{
$user = $this->user; // Just saved you typing five characters
// At this point the container is available
}
}
На самом деле я не настраиваю службу безопасности, потому что она станет доступна позже через контейнер.
Если вы хотите сделать это для обеспечения контроля доступа для всего класса, вы можете использовать аннотации Security:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
/**
* @IsGranted('ROLE_USER')
*/
class TestController extends AbstractController
{
// Only authenticated user will be able to access this methods
}
НИКОГДА НЕ ИСПОЛЬЗОВАТЬ $security->getUser()
или же $this->getUser()
в конструкторе!!
аутентификация может быть еще не завершена. (В службе вместо этого сохраните весь объект безопасности.:
symfony.com/doc/security.html#a-fetching-the-user-object
... и вы можете использовать $this->getUser()
в любом контроллере, который расширяется с помощью AbstractController. (Только не в конструкторе)