¿Cómo obtengo la entidad que representa al usuario actual en Symfony2?

136

Estoy usando la configuración de seguridad de Symfony. Todo funciona bien, pero no sé cómo hacer una cosa importante:

En Twig, puedo llegar a la información del usuario actual haciendo:

Welcome, {{ app.user.username }}

o similar

¿Cómo accedo a esta misma información en el controlador? Específicamente, quiero obtener la entidad de usuario actual para poder almacenarla relacionalmente en otra entidad (mapeo uno a uno).

Realmente esperaba que fuera

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

Pero eso no funciona. Me da una clase de tipo

Symfony\Component\Security\Core\User\User

y quiero uno de tipo

Acme\AuctionBundle\Entity\User

cual es mi entidad ...

Robert Martin
fuente

Respuestas:

209

Symfony 4+, enfoque 2019+

En Symfony 4 (probablemente también 3.3, pero solo probado en 4) puede inyectar el Securityservicio a través del cableado automático en el controlador de esta manera:

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

Como dice @ktolis, primero debes configurar tu /app/config/security.yml.

Luego con

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

debería ser suficiente!

$useres tu objeto de usuario! No necesita consultarlo nuevamente.

Descubra la forma de configurar sus proveedores security.ymldesde la Documentación Sf2 e intente nuevamente.

¡La mejor de las suertes!

Cristian Douce
fuente
¿Qué sucede si necesito la entidad de usuario en una plantilla PHP?
DomingoSL
@DomingoSL Consulte el siguiente enlace de la documentación oficial: symfony.com/doc/master/book/…
Cristian Douce
55
Desde Symfony 2.6, el servicio security.context ha quedado obsoleto y dividido en dos nuevos servicios: security.authorization_checker y security.token_storage. Puede verificar la forma correcta de obtener el usuario actual aquí: symfony.com/blog/…
jmleroux
Estoy en Symfony 5.1.2 y en adelante $user = $this->security->getUser();, $usersiempre es nullpara mí, esté o no conectado.
Nick Rolando
Oh, parece que es porque estoy haciendo esto en un suscriptor de eventos, y esto aún no se ha inicializado tan temprano en la solicitud.
Nick Rolando
62

Mejores prácticas

De acuerdo con la documentación desde Symfony 2.1, simplemente use este acceso directo:

$user = $this->getUser();

Lo anterior aún funciona en Symfony 3.2 y es un atajo para esto:

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

El security.token_storageservicio se introdujo en Symfony 2.6. Antes de Symfony 2.6, tenía que usar el getToken()método del security.contextservicio.

Ejemplo : y si desea directamente el nombre de usuario:

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

Si el tipo de clase de usuario es incorrecto

El usuario será un objeto y la clase de ese objeto dependerá de su proveedor de usuario .

Antoine Subit
fuente
6

El hilo es un poco viejo, pero creo que esto probablemente podría ahorrarle tiempo a alguien ...

Me encontré con el mismo problema que la pregunta original, que el tipo se muestra como Symfony \ Component \ Security \ Core \ User \ User

Finalmente resultó que estaba conectado usando un usuario en memoria

my security.yml se parece a esto

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

el tipo de usuario in_memory siempre es Symfony \ Component \ Security \ Core \ User \ User si desea utilizar su propia entidad, inicie sesión con el usuario de ese proveedor.

Gracias hj

hj '
fuente
4

En Symfony> = 3.2, la documentación indica que:

Una forma alternativa de obtener el usuario actual en un controlador es insinuar el argumento del controlador con UserInterface (y predeterminarlo a nulo si iniciar sesión es opcional):

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

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

Esto solo se recomienda para desarrolladores experimentados que no se extienden desde el controlador base de Symfony y tampoco usan el ControllerTrait . De lo contrario, se recomienda seguir usando el acceso directo getUser ().

Publicación de blog al respecto

Nikita U.
fuente
Esto me ayudó mucho al tratar de obtener el usuario actual en un EventSubscriber: tuve que conectar automáticamente (Security $ security) como parámetro en __construct y luego usar $ security-> getUser () y ¡voilà!
tsadiq
2
$this->container->get('security.token_storage')->getToken()->getUser();
Alenko Verzina
fuente
2
Bienvenido a stackoverflow. Por favor explique sobre la respuesta. stackoverflow.com/help/how-to-answer
Rohan Khude
-36

Bueno, primero debe solicitar el nombre de usuario del usuario de la sesión en la acción de su controlador de esta manera:

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

luego haga una consulta a la base de datos y obtenga su objeto con 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();

el $ user ahora debería mantener al usuario con este nombre de usuario (también podría usar otros campos, por supuesto)

... pero primero deberá configurar su /app/config/security.yml para usar el campo apropiado para su proveedor de seguridad de la siguiente manera:

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

¡espero que esto ayude!

ktolis
fuente
Bueno, Martin, o quieres el usuario O el nombre de usuario. La decisión es tuya. Es su responsabilidad obtener el objeto que necesita. Y como dijiste, no quieres el usuario normal sino el usuario del espacio de nombres Acme.
ktolis
66
"SELECCIONE U DE Acme \ AuctionBundle \ Entity \ User u where u.username =". $ Username; = DEBE USAR CONSULTAS PARAMETRIZADAS!
CappY
1
$this->get('security.context')->getToken()->getUser()en sí mismo le proporciona el objeto de usuario conectado. No tiene que volver a consultarlo. De hecho, ¿qué versión estabas usando?
Jeet