2013-06-10 13 views
5

Używam symfony2 i FOSUserBundle.Jak zdobyć userid od Eventlistenera, które są wywoływane z AJAX

Normalnie mogę uzyskać dane użytkownika od kontrolera

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

lub

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

Ale teraz chcę, aby uzyskać UserData z eventlistner które są wywoływane z Ajax.

Czy to możliwe? albo nie?

moje źródło jest tutaj.

namespace Acme\MemberBundle\EventListener; 

    use ADesigns\CalendarBundle\Event\CalendarEvent; 
    use ADesigns\CalendarBundle\Entity\EventEntity; 
    use Doctrine\ORM\EntityManager; 

    class CalendarEventListener 
    { 
     private $entityManager; 

     public function __construct(EntityManager $entityManager) 
     { 
      $this->entityManager = $entityManager; 
     } 

     public function loadEvents(CalendarEvent $calendarEvent) 
     { 
      $startDate = $calendarEvent->getStartDatetime(); 
      $endDate = $calendarEvent->getEndDatetime(); 


      $user = $this->container->get('security.context')->getToken()->getUser();//it doesnt work 

      // load events using your custom logic here, 
      // for instance, retrieving events from a repository 

      $companyEvents = $this->entityManager->getRepository('UserBundle:MutorSche') 
        ->createQueryBuilder('company_events') 
        ->where('company_events.event_datetime BETWEEN :startDate and :endDate') 
        ->setParameter('startDate', $startDate->format('Y-m-d H:i:s')) 
        ->setParameter('endDate', $endDate->format('Y-m-d H:i:s')) 
        ->getQuery()->getResults(); 



      foreach($companyEvents as $companyEvent) { 

       // create an event with a start/end time, or an all day event 
       if ($companyEvent->getAllDayEvent() === false) { 
        $eventEntity = new EventEntity($companyEvent->getTitle(), $companyEvent->getStartDatetime(), $companyEvent->getEndDatetime()); 
       } else { 
        $eventEntity = new EventEntity($companyEvent->getTitle(), $companyEvent->getStartDatetime(), null, true); 
       } 

       //optional calendar event settings 
       $eventEntity->setAllDay(true); // default is false, set to true if this is an all day event 
       $eventEntity->setBgColor('#FF0000'); //set the background color of the event's label 
       $eventEntity->setFgColor('#FFFFFF'); //set the foreground color of the event's label 
       $eventEntity->setUrl('http://www.google.com'); // url to send user to when event label is clicked 
       $eventEntity->setCssClass('my-custom-class'); // a custom class you may want to apply to event labels 

       //finally, add the event to the CalendarEvent for displaying on the calendar 
       $calendarEvent->addEvent($eventEntity); 
      } 
     } 
    } 

zgodnie z radą @ nifr.

Zmieniłem trochę w moim kręgowego źródłowym jak

class CalendarEventListener 
{ 
    private $entityManager; 
    private $container;//add 

    public function __construct(
      EntityManager $entityManager, 
      ContainerInterface $container)//add 
    { 
     $this->entityManager = $entityManager; 
     $this->container = $container;//add 
    } 

następnie chcę przekazać Drugi argument eventlistner. Używam pliku services.xml do utworzenia detektora. Jak mogę dodać drugi argument w tej sprawie?

<?xml version="1.0" encoding="UTF-8" ?> 
     <container xmlns="http://symfony.com/schema/dic/services"> 

     <services> 
      <service id="acme.memberbundle.calendar_listener" class="Acme\MemberBundle\EventListener\CalendarEventListener"> 
       <argument type="service" id="doctrine.orm.entity_manager" /> 
       <tag name="kernel.event_listener" event="calendar.load_events" method="loadEvents" /> 
      </service> 

     </services> 
     </container> 

Odpowiedz

5

trzeba wstrzyknąć do pojemnika przez Dependency Injection klasie słuchacza, aby go acccess.

Przeczytaj więcej na ten temat w artykule book chapter.

your.listener: 
    class: Acme\MemberBundle\EventListener\CalendarEventListener 
    arguments: ["@service_container"] 

Chociaż wstrzykiwanie cały pojemnik jest wydajność mądry nie najlepszy pomysł wśród niektórych innych powodów, takich jak sprawdzalności (normalnie tylko trzeba wstrzyknąć usługi niezbędne w swojej klasie zamiast pojemnika) ...

... w twoim przypadku, jeśli nie korzystasz z opcji UserCallable, otrzymasz okólnik podczas wstrzykiwania @security.context.

Więc najszybszym rozwiązaniem jest wstrzyknięcie pojemnik i dostosowanie konstruktora Twojego słuchacza:

private $container; 

public function __construct(ContainerInterface $container) 
{ 
    $this->container = $container; 
} 



public function someOtherMethod() 
{ 
    $user = $this->container->get('security.context')->getToken()->getUser(); 

    // ... 
} 
+0

dziękuję @nifr prawie dostać .W moim przypadku, muszę zdać dwa argumenty do detektora zdarzeń zarówno EntityManager i kontener Więc zmieniłem źródło i dodano do głównego artykułu. Czy możesz to sprawdzić? – whitebear

+0

Możliwe jest dodawanie wielu argumentów, wystarczy dodać kolejny węzeł xml '' ale nie potrzebujesz dwóch argumentów w twoim przypadku ... możesz uzyskać entityManager od kontener również ... '$ this-> entityManager = $ container-> get ('doctrine.orm.entity_manager')' w konstruktorze. – nifr

+0

Widzę. @ Nifr ale " 'mówi Usługa" acme.memberbundle.calendar_listener "ma zależność od nieistniejącego" kontenera "usługi. Prawie się tam dostaję ... chociaż .. dzięki za wsparcie. – whitebear

9

Jak z Symfony 2.6 ten problem powinien być rozwiązany. Żądanie ściągnięcia zostało właśnie zaakceptowane do wzorca. Twój problem został opisany tutaj. https://github.com/symfony/symfony/pull/11690

Od Symfony 2.6 możesz wprowadzić security.token_storage do swojego słuchacza. Ta usługa będzie zawierać token używany przez SecurityContext w < = 2,5. W wersji 3.0 ta usługa całkowicie zastąpi usługę SecurityContext::getToken(). Tutaj możesz zobaczyć podstawową listę zmian: http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements#deprecated-the-security-context-service

Przykładowe użycie w 2.6:

Konfiguracja:

services: 
    my.listener: 
     class: EntityListener 
     arguments: 
      - "@security.token_storage" 
     tags: 
      - { name: doctrine.event_listener, event: prePersist } 


słuchacz

use Doctrine\ORM\Event\LifecycleEventArgs; 
use Symfony\Component\DependencyInjection\ContainerInterface; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; 

class EntityListener 
{ 
    private $token_storage; 

    public function __construct(TokenStorageInterface $token_storage) 
    { 
     $this->token_storage = $token_storage; 
    } 

    public function prePersist(LifeCycleEventArgs $args) 
    { 
     $entity = $args->getEntity(); 
     $entity->setCreatedBy($this->token_storage->getToken()->getUsername()); 
    } 
} 
+1

To jest teraz poprawna odpowiedź! – Acyra

3

Pamiętaj, aby nie mieć Symfony profiler/toolbar włączony. Nie wiem dlaczego, ale za każdym razem przynosiło $this->container->get('security.context')->getToken() powrotu.

W pliku, config_dev.yml upewnij się, że ustawiony jest następujący:

web_profiler: 
    toolbar: false 
+1

Nienawidzę tego, gdy moje odpowiedzi są odrzucane bez wyjaśnienia, dlaczego. To było uzasadnione rozwiązanie dla mnie. – craned

Powiązane problemy