如何从eventlistener获取从AJAX调用的userid

whi*_*ear 8 symfony fosuserbundle

我正在使用symfony2和FOSUserBundle.

通常,我可以从Controller获取用户数据

$user = $this->get('security.context')->getToken()->getUser();
Run Code Online (Sandbox Code Playgroud)

要么

$user = $this->container->get('security.context')->getToken()->getUser(); 
Run Code Online (Sandbox Code Playgroud)

但是现在,我想从eventlistner获取从Ajax调用的userdata.

可能吗?或不?

我的来源在这里.

    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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

根据@nifr的建议.

我在源代码中改变了一下

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

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

然后我想将第二个参数传递给eventlistner.我正在使用services.xml来创建监听器.我怎样才能在此添加第二个参数?

 <?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>
Run Code Online (Sandbox Code Playgroud)

Any*_*one 17

从Symfony 2.6开始,这个问题应该修复.拉取请求刚刚被主人接受.您的问题在此处描述. https://github.com/symfony/symfony/pull/11690

从Symfony 2.6开始,您可以将其security.token_storage注入您的监听器.此服务将包含SecurityContextin <= 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 }
Run Code Online (Sandbox Code Playgroud)


你的倾听者

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());
    }
}
Run Code Online (Sandbox Code Playgroud)


Nic*_*ich 5

您需要通过依赖注入将容器注入到侦听器类中才能使用它.

本书的章节中阅读更多相关内容.

your.listener:
    class: Acme\MemberBundle\EventListener\CalendarEventListener
    arguments: ["@service_container"]
Run Code Online (Sandbox Code Playgroud)

尽管注入整个容器在性能方面并不是最好的想法,还有一些其他原因,比如可测试性(你通常只需要在你的类而不是容器中注入你需要的服务)......

...在您的情况下,如果您没有使用UserCallable,您将在注入时获得循环引用@security.context.

所以最快的解决方案是注入容器并调整监听器的构造函数:

private $container;

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



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

    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 您应该只注入您不需要的容器服务. (2认同)

cra*_*ned 5

一定不要Symfony profiler/toolbar打开.我不知道为什么,但每次都$this->container->get('security.context')->getToken()回来了null.

在文件中,config_dev.yml确保设置以下内容:

web_profiler:
  toolbar: false
Run Code Online (Sandbox Code Playgroud)

  • 当我的答案被否决而没有解释为什么时,我讨厌它.这对我来说是一个合法的解决方案. (3认同)