Метод 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. (Только не в конструкторе)

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