Como obtenho a entidade que representa o usuário atual no Symfony2?

136

Estou usando a configuração de segurança do Symfony. Tudo funciona bem, mas não sei como fazer uma coisa importante:

No galho, posso acessar as informações do usuário atual fazendo:

Welcome, {{ app.user.username }}

ou similar

Como acesso essas mesmas informações no controlador? Especificamente, desejo obter a entidade do usuário atual para poder armazená-la de forma relacional em outra entidade (mapeamento um a um).

Eu estava realmente esperando que fosse

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

mas isso não funciona. Isso me dá uma classe do tipo

Symfony\Component\Security\Core\User\User

e eu quero um do tipo

Acme\AuctionBundle\Entity\User

qual é a minha entidade ....

Robert Martin
fonte

Respostas:

209

Symfony 4+, 2019+ Abordagem

No symfony 4 (provavelmente 3.3 também, mas apenas testado em 4), você pode injetar o Securityserviço via fiação automática no controlador desta forma:

<?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- Abordagem

Como o @ktolis diz, primeiro você precisa configurar o seu /app/config/security.yml.

Então com

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

deve ser suficiente!

$useré seu objeto de usuário! Você não precisa consultá-lo novamente.

Descobrir a maneira de configurar seus fornecedores no security.ymlde Documentação Sf2 e tente novamente.

Boa sorte!

Cristian Douce
fonte
E se eu precisar da entidade do usuário em um modelo PHP?
DomingoSL
@DomingoSL Verifique o seguinte link na documentação oficial: symfony.com/doc/master/book/…
Cristian Douce
5
Desde o Symfony 2.6, o serviço security.context foi descontinuado e dividido em dois novos serviços: security.authorization_checker e security.token_storage. Você pode verificar a maneira correta de buscar o usuário atual aqui: symfony.com/blog/…
jmleroux
Estou no Symfony 5.1.2 e continuo $user = $this->security->getUser();, $useré sempre nullpara mim, conectado ou não.
Nick Rolando
Ah, parece que é porque eu estou fazendo isso em um Assinante de Eventos, e isso ainda não foi inicializado tão cedo na solicitação.
Nick Rolando
62

Melhor prática

De acordo com a documentação desde o Symfony 2.1, basta usar este atalho:

$user = $this->getUser();

O exemplo acima ainda está funcionando no Symfony 3.2 e é um atalho para isso:

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

O security.token_storageserviço foi introduzido no Symfony 2.6. Antes do Symfony 2.6, você tinha que usar o getToken()método do security.contextserviço.

Exemplo : E se você quiser diretamente o nome de usuário:

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

Se tipo de classe de usuário errado

O usuário será um objeto e a classe desse objeto dependerá do seu provedor de usuários .

Antoine Subit
fonte
6

O tópico é um pouco antigo, mas acho que isso provavelmente poderia economizar o tempo de alguém ...

Encontrei o mesmo problema da pergunta original, que o tipo é mostrado como Symfony \ Component \ Security \ Core \ User \ User

Acabou que eu estava logado usando um usuário na memória

meu security.yml se parece com isso

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' ] }

o tipo de usuário in_memory é sempre Symfony \ Componente \ Segurança \ Núcleo \ Usuário \ Usuário, se você quiser usar sua própria entidade, efetue login usando o usuário desse fornecedor.

Obrigado hj

hj '
fonte
4

No symfony> = 3.2, a documentação afirma que:

Uma maneira alternativa de obter o usuário atual em um controlador é digitar o argumento do controlador com UserInterface (e usar como padrão nulo se o login for opcional):

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

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

Isso é recomendado apenas para desenvolvedores experientes que não se estendem do controlador básico Symfony e também não usam o ControllerTrait . Caso contrário, é recomendável continuar usando o atalho getUser ().

Postagem sobre o blog

Nikita U.
fonte
Isso me ajudou muito ao tentar obter o usuário atual em um EventSubscriber: eu tive que conectar automaticamente (Security $ security) como parâmetro no __construct e usar $ security-> getUser () e pronto!
tsadiq 5/09/19
2
$this->container->get('security.token_storage')->getToken()->getUser();
Alenko Verzina
fonte
2
Bem-vindo ao stackoverflow. Por favor, explique sobre a resposta. stackoverflow.com/help/how-to-answer
Rohan Khude
-36

Bem, primeiro você precisa solicitar o nome de usuário do usuário da sessão em sua ação do controlador da seguinte maneira:

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

faça uma consulta ao banco de dados e obtenha seu objeto com dql regular como

$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();

o $ user agora deve reter o usuário com esse nome de usuário (você também pode usar outros campos)

... mas você deverá primeiro configurar sua configuração /app/config/security.yml para usar o campo apropriado para seu provedor de segurança da seguinte maneira:

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

espero que isto ajude!

ktolis
fonte
Bem, Martin, você quer o usuário OU o nome de usuário. A escolha é sua. É sua responsabilidade obter o objeto que você precisa. E como você disse, não deseja o usuário comum, mas o usuário do espaço para nome Acme.
Ktolis 13/10
6
"SELECT u FROM Acme \ AuctionBundle \ Entity \ User u onde u.username =". $ Username; = VOCÊ DEVE USAR CONSULTAS PARAMETRIZADAS!
CappY #
1
$this->get('security.context')->getToken()->getUser()ele recebe o objeto de usuário conectado. Você não precisa consultá-lo novamente. De fato, qual versão você estava usando?
Jeet