Jak uzyskać jednostkę reprezentującą bieżącego użytkownika w Symfony2?

136

Używam ustawień bezpieczeństwa Symfony. Wszystko działa dobrze, ale nie wiem, jak zrobić jedną ważną rzecz:

W twig mogę dotrzeć do informacji o aktualnym użytkowniku, wykonując:

Welcome, {{ app.user.username }}

lub podobne

Jak uzyskać dostęp do tych samych informacji w kontrolerze? W szczególności chcę uzyskać bieżącą jednostkę użytkownika, aby móc przechowywać ją w relacji w innej encji (mapowanie jeden do jednego).

Naprawdę miałam nadzieję, że tak będzie

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

ale to nie działa. To daje mi klasę typu

Symfony\Component\Security\Core\User\User

i chcę jednego typu

Acme\AuctionBundle\Entity\User

który jest moim bytem ...

Robert Martin
źródło

Odpowiedzi:

209

Podejście do Symfony 4+, 2019+

W symfony 4 (prawdopodobnie również 3.3, ale tylko w rzeczywistości przetestowane w 4) możesz wstrzyknąć Securityusługę przez automatyczne okablowanie w kontrolerze w następujący sposób:

<?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 - Podejście

Jak mówi @ktolis, najpierw musisz skonfigurować swój /app/config/security.yml.

Następnie z

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

powinno wystarczyć!

$userto Twój obiekt użytkownika! Nie musisz ponownie pytać.

Znaleźć sposób, aby skonfigurować dostawców w security.ymlod SF2 Dokumentacji i spróbuj ponownie.

Powodzenia!

Cristian Douce
źródło
A jeśli potrzebuję encji użytkownika w szablonie PHP?
DomingoSL
@DomingoSL Sprawdź poniższy link w oficjalnej dokumentacji: symfony.com/doc/master/book/…
Cristian Douce
5
Od Symfony 2.6 usługa security.context została wycofana i podzielona na dwie nowe usługi: security.authorization_checker i security.token_storage. Możesz sprawdzić poprawny sposób pobierania bieżącego użytkownika tutaj: symfony.com/blog/ ...
jmleroux
Jestem na Symfony 5.1.2 i dalej $user = $this->security->getUser();, $userjest zawsze nulldla mnie, niezależnie od tego, czy jestem zalogowany, czy nie.
Nick Rolando
Och, wygląda na to, że robię to w subskrybencie wydarzenia, a to nie zostało jeszcze zainicjowane na tak wczesnym etapie żądania.
Nick Rolando
62

Najlepsze praktyki

Zgodnie z dokumentacją od Symfony 2.1 po prostu użyj tego skrótu:

$user = $this->getUser();

Powyższe nadal działa w Symfony 3.2 i jest skrótem do tego:

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

security.token_storageUsługa została wprowadzona w Symfony 2.6. Przed Symfony 2.6 trzeba było używać getToken()metody security.contextusługi.

Przykład : A jeśli chcesz bezpośrednio nazwę użytkownika:

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

Jeśli zły typ klasy użytkownika

Użytkownik będzie obiektem, a klasa tego obiektu będzie zależeć od dostawcy użytkownika .

Antoine Subit
źródło
6

Wątek jest trochę stary, ale myślę, że to prawdopodobnie mogłoby zaoszczędzić komuś czas ...

Napotkałem ten sam problem, co pierwotne pytanie, że typ jest wyświetlany jako Symfony \ Component \ Security \ Core \ User \ User

Ostatecznie okazało się, że zalogowałem się za pomocą użytkownika w pamięci

mój plik security.yml wygląda mniej więcej tak

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

typ użytkownika in_memory to zawsze Symfony \ Component \ Security \ Core \ User \ User, jeśli chcesz użyć własnej encji, zaloguj się przy użyciu użytkownika tego dostawcy.

Dzięki, hj

hj '
źródło
4

W symfony> = 3.2, dokumentacja stwierdza, że:

Alternatywnym sposobem na pobranie bieżącego użytkownika w kontrolerze jest wskazanie argumentu kontrolera za pomocą interfejsu UserInterface (i domyślnej wartości null, jeśli zalogowanie jest opcjonalne):

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

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

Jest to zalecane tylko dla doświadczonych programistów, którzy nie korzystają z podstawowego kontrolera Symfony i nie używają również właściwości kontrolera . W przeciwnym razie zaleca się dalsze używanie skrótu getUser ().

Wpis na blogu o tym

Nikita U.
źródło
Bardzo mi to pomogło podczas próby uzyskania aktualnego użytkownika w EventSubscriber: musiałem autowire (Security $ security) jako parametr w __construct, a następnie użyć $ security-> getUser () i voilà!
tsadiq
2
$this->container->get('security.token_storage')->getToken()->getUser();
Alenko Verzina
źródło
2
Witamy w stackoverflow. Proszę wyjaśnić odpowiedź. stackoverflow.com/help/how-to-answer
Rohan Khude
-36

Cóż, najpierw musisz poprosić o nazwę użytkownika z sesji w akcji kontrolera w następujący sposób:

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

następnie wyślij zapytanie do bazy danych i pobierz obiekt za pomocą zwykłego dql, takiego jak

$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 powinien teraz trzymać użytkownika z tą nazwą użytkownika (możesz oczywiście użyć innych pól)

... ale będziesz musiał najpierw skonfigurować konfigurację /app/config/security.yml, aby używała odpowiedniego pola dla twojego dostawcy zabezpieczeń, jak na przykład:

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

mam nadzieję że to pomoże!

ktolis
źródło
Martin, albo chcesz użytkownika, albo nazwę użytkownika. Wybór nalezy do ciebie. Twoim obowiązkiem jest zdobycie potrzebnego przedmiotu. I jak powiedziałeś, nie chcesz zwykłego użytkownika, ale użytkownika przestrzeni nazw Acme.
ktolis
6
„SELECT u FROM Acme \ AuctionBundle \ Entity \ User u, gdzie u.username =”. $ Username; = POWINIENEŚ UŻYWAĆ PARAMETRYCZNYCH PYTAŃ!
CappY
1
$this->get('security.context')->getToken()->getUser()sama pobiera zalogowany obiekt użytkownika. Nie musisz ponownie odpytywać. Właściwie jakiej wersji używasz?
Jeet