2013-06-10 11 views
5

symfony2とFOSUserBundleを使用しています。AJAXから呼び出されたeventlistenerからユーザーIDを取得する方法

通常、私はコントローラ

からユーザデータを取得することができ
$user = $this->get('security.context')->getToken()->getUser(); 

または

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

しかし、今、私は、Ajaxから呼び出されeventlistnerからユーザデータを取得したいです。

可能ですか?か否か?

マイソースはここにあります。

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); 
      } 
     } 
    } 

@ nifrのアドバイスに従って。

私はその後、私はeventlistnerに2つ目の引数を渡したい

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

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

ように私のソースコードに少し変更。 私はリスナーを作るためにservices.xmlを使用しています。 これに第2引数を追加するにはどうすればよいですか?

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

答えて

5

アクセサーするには、コンテナをDependency Injection経由でリスナークラスに注入する必要があります。

book chapterで詳しく読むことができます。

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

容器全体を注入すると、性能面ではないテスト容易性のようないくつかの他の理由との間で最高のアイデア(普段だけではなく、コンテナのクラスで必要なサービスを注入しなければならない)ですが...

...あなたがUserCallableを使用していない場合は、@security.contextを注入するときに循環参照を取得します。

だから、最も早い解決策は、コンテナを注入して、リスナーのコンストラクタ調整されています。この問題が修正されなければならないのSymfony 2.6のとおり

private $container; 

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



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

    // ... 
} 
+0

はありがとう、私はほとんど私の場合.INそれを得る を@nifr、私は両方のEntityManagerのイベントリスナーに二つの引数を渡す必要があり、コンテナ ソースを変更してメイン記事に追加しました。よろしくお願いします。 – whitebear

+0

複数の引数を追加することができます。別のxmlノード 'を追加することは可能ですが、2つの引数は必要ありません。コンテナも '$ this-> entityManager = $ container-> get( 'doctrine.orm.entity_manager')'をコンストラクタに入れてください。 – nifr

+0

私は参照してください。@ nifr ''サービス "acme.memberbundle.calendar_listener"は存在しないサービス "container"に依存しています。 ...あなたのご支援に感謝します。 – whitebear

9

を。プル要求がマスターに受け入れられました。あなたの問題はここに記述されています。 https://github.com/symfony/symfony/pull/11690

symfony 2.6では、security.token_storageをリスナーに注入することができます。このサービスにはSecurityContextで使用されているトークンが< = 2.5に含まれます。 3.0では、このサービスはSecurityContext::getToken()の代わりになります。ここでは基本的な変更リストを見ることができます:http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements#deprecated-the-security-context-service

2の使用例。6:

あなたの設定:

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


あなたのリスナー

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

これは正解になりました! – Acyra

3

Symfony profiler/toolbarがオンになっていないようにしてください。私は理由を知らないが、それは$this->container->get('security.context')->getToken()返信null毎回です。ファイルで

config_dev.yml次が設定されていることを確認します

web_profiler: 
    toolbar: false 
+1

なぜ私の答えが何の説明もなく投票されたとき、私はそれが嫌いです。これは私にとって正当な解決策でした。 – craned

関連する問題