Как получить сущность, которая представляет текущего пользователя в Symfony2?

136

Я использую настройки безопасности Symfony. Все отлично работает, но я не знаю, как сделать одну важную вещь:

В ветке я могу получить информацию о текущем пользователе, выполнив:

Welcome, {{ app.user.username }}

или похожие

Как мне получить доступ к этой же информации в контроллере? В частности, я хочу получить текущий пользовательский объект, чтобы я мог сохранить его реляционно в другом объекте (сопоставление один-к-одному).

Я действительно надеялся, что это будет

$this->get('security.context')->getToken()->getUser()

но это не работает Это дает мне класс типа

Symfony\Component\Security\Core\User\User

и я хочу один из типа

Acme\AuctionBundle\Entity\User

которая моя сущность ....

Роберт Мартин
источник

Ответы:

209

Symfony 4+, подход 2019+

В Symfony 4 (возможно, также 3.3, но только в 4), вы можете внедрить Securityслужбу через автоматическое подключение к контроллеру следующим образом:

<?php

use Symfony\Component\Security\Core\Security;

class SomeClass
{
    /**
     * @var Security
     */
    private $security;

    public function __construct(Security $security)
    {
       $this->security = $security;
    }

    public function privatePage() : Response
    {
        $user = $this->security->getUser(); // null or UserInterface, if logged in
        // ... do whatever you want with $user
    }
}

Symfony 2 - Подход

Как говорит @ktolis, сначала нужно настроить свой /app/config/security.yml.

Затем с

$user = $this->get('security.token_storage')->getToken()->getUser();
$user->getUsername();

должно быть достаточно!

$userваш пользовательский объект! Вам не нужно запрашивать его снова.

Узнайте, как настроить ваши поставщик в security.ymlот SF2 документации и попробовать еще раз.

Удачи!

Кристиан Дус
источник
Что если мне понадобится пользовательский объект в шаблоне PHP?
DomingoSL
@DomingoSL Проверьте следующую ссылку в официальной документации: symfony.com/doc/master/book/…
Кристиан Дус
5
Начиная с Symfony 2.6, служба security.context устарела и разделена на две новые службы: security.authorization_checker и security.token_storage. Вы можете проверить правильный способ получения текущего пользователя здесь: symfony.com/blog/…
jmleroux
Я на Symfony 5.1.2 и дальше $user = $this->security->getUser();, $userвсегда nullдля меня, вне зависимости от того, залогинен я или нет.
Ник Роландо
О, похоже, это потому, что я делаю это в подписчике на событие, и это еще не инициализировано в начале запроса.
Ник Роландо
62

Лучшая практика

Согласно документации, начиная с Symfony 2.1, просто используйте этот ярлык:

$user = $this->getUser();

Выше все еще работает на Symfony 3.2 и является ярлыком для этого:

$user = $this->get('security.token_storage')->getToken()->getUser();

security.token_storageУслуга была введена в Symfony 2.6. До Symfony 2.6 вам приходилось использовать getToken()метод security.contextсервиса.

Пример : И если вы хотите напрямую имя пользователя:

$username = $this->getUser()->getUsername();

Если неправильный тип пользовательского класса

Пользователь будет объектом, и класс этого объекта будет зависеть от вашего провайдера .

Антуан Субит
источник
6

Нить немного старая, но я думаю, что это может сэкономить чье-то время ...

Я столкнулся с той же проблемой, что и исходный вопрос, что тип показан как Symfony \ Component \ Security \ Core \ User \ User

В конце концов оказалось, что я вошел в систему, используя пользователя в памяти

мой security.yml выглядит примерно так

security:
    providers:
        chain_provider:
            chain:
                providers: [in_memory, fos_userbundle]
        fos_userbundle:
            id: fos_user.user_manager
        in_memory:
            memory:
                users:
                    user:  { password: userpass, roles: [ 'ROLE_USER' ] }
                    admin: { password: adminpass, roles: [ 'ROLE_ADMIN', 'ROLE_SONATA_ADMIN' ] }

тип пользователя in_memory всегда Symfony \ Component \ Security \ Core \ User \ User, если вы хотите использовать свою собственную сущность, войдите в систему, используя пользователя этого провайдера.

Спасибо hj

HJ»
источник
4

В symfony> = 3.2 документация гласит:

Альтернативный способ получить текущего пользователя в контроллере состоит в том, чтобы напечатать подсказку контроллера с параметром UserInterface (и по умолчанию он равен нулю, если вход в систему необязателен):

use Symfony\Component\Security\Core\User\UserInterface\UserInterface;

public function indexAction(UserInterface $user = null)
{
    // $user is null when not logged-in or anon.
}

Это рекомендуется только для опытных разработчиков, которые не выходят за пределы базового контроллера Symfony и не используют ControllerTrait . В противном случае рекомендуется продолжать использовать ярлык getUser ().

Сообщение в блоге об этом

Никита У.
источник
Это очень помогло мне при попытке получить текущего пользователя в EventSubscriber: мне пришлось автоматически связать (Security $ security) в качестве параметра в __construct, затем использовать $ security-> getUser () и вуаля!
Цадик
2
$this->container->get('security.token_storage')->getToken()->getUser();
Аленко Верзина
источник
2
Добро пожаловать в stackoverflow. Пожалуйста, объясните об ответе. stackoverflow.com/help/how-to-answer
Рохан Худе
-36

Ну, во-первых, вам нужно запросить имя пользователя пользователя из сеанса в вашем действии контроллера следующим образом:

$username=$this->get('security.context')->getToken()->getUser()->getUserName();

затем сделайте запрос к БД и получите ваш объект с обычным dql, как

$em = $this->get('doctrine.orm.entity_manager');    
"SELECT u FROM Acme\AuctionBundle\Entity\User u where u.username=".$username;
$q=$em->createQuery($query);
$user=$q->getResult();

$ user теперь должен содержать пользователя с этим именем пользователя (вы также можете использовать другие поля)

... но вам сначала нужно будет настроить конфигурацию /app/config/security.yml, чтобы использовать соответствующее поле для вашего провайдера безопасности, например так:

security:
 provider:
  example:
   entity: {class Acme\AuctionBundle\Entity\User, property: username}

надеюсь это поможет!

ktolis
источник
Ну, Мартин, вы либо хотите пользователя, либо имя пользователя. Выбор за вами. Вы несете ответственность за получение нужного вам объекта. И, как вы сказали, вам нужен не обычный пользователь, а пользователь пространства имен Acme.
Ктолис
6
"SELECT u FROM Acme \ AuctionBundle \ Entity \ User u, где u.username =". $ Username; = ВЫ ДОЛЖНЫ ИСПОЛЬЗОВАТЬ ПАРАМЕТРИРОВАННЫЕ ЗАПРОСЫ!
CappY
1
$this->get('security.context')->getToken()->getUser()сам получает вам залогиненный пользовательский объект. Вам не нужно запрашивать его снова. На самом деле, какую версию вы использовали?
Джит