Symfony2事件监听器问题

时间:2015-02-16 20:15:33

标签: php symfony

理解事件监听器时遇到一些麻烦。我的控制器中有以下操作

public function createAction(Request $request)
{
   try {
        $na_command = strtoupper($request->get('na_command'));
        $na_is_connecting = $request->get('na_is_connecting');

        // ==== validate (removed) ==== // 

        $em = $this->getDoctrine()->getManager();

        $alert = new AvailabilityAlert();
        $alert->setSearchCommand($na_command);
        $alert->setIsConnecting($na_is_connecting);
        $em->persist($alert);

        $em->flush();

        return new JsonResponse('Success');

    }catch (Exception $e) {
    }

}

我有一个普通的表单(不是表单构建器),我从数据创建一个Alert并将其发送到我的数据库。如果成功,会将成功消息发送回我的ajax。

这就是问题所在。如果createAction成功,我需要它将警报发送到另一个类并用它做一些事情。所以有人建议事件监听器可以为我做这个。所以我创建了一个测试的监听器

<?php

namespace Nick\AlertBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;

class AvailabilityAlertListener
{

    public function prePersist(LifecycleEventArgs $args)
    {
        die('Something is being inserted!');
    }

}

然后我将它添加到services.yml

services:
    doctrine.availability_alert_listener:
        class: Nick\AlertBundle\EventListener\AvailabilityAlertListener
        arguments: []
        tags:
            - { name: doctrine.event_listener, event: prePersist }

但是,如何让createAction监听此事件?我有点失落,所以任何建议都会欣赏。基本上,在createAction结束时,我想做类似

的事情
include 'uapi_cron_single.php';
AddFlightsAction($alert);

但我不想像上面那样做,因为它很乱。但是如果createAction成功,我需要将警报发送到另一个类,那么最好的方法是什么呢?

由于

2 个答案:

答案 0 :(得分:2)

首先,当你定义一个没有参数的服务时,你不必指定arguments: [],你可以简单地写一下

services:
    doctrine.availability_alert_listener:
        class: Nick\AlertBundle\EventListener\AvailabilityAlertListener
        tags:
            - { name: doctrine.event_listener, event: prePersist }

其次,您知道在实体持久化之前该事件将被解雇吗?我认为这不是你想要的(我想),因为你在写对象插入数据库后触发事件。因此,您应该按如下方式修改服务定义

services:
    doctrine.availability_alert_listener:
        class: Nick\AlertBundle\EventListener\AvailabilityAlertListener
        tags:
            - { name: doctrine.event_listener, event: postPersist }

和您的服务类

<?php

namespace Nick\AlertBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;

class AvailabilityAlertListener
{

    public function postPersist(LifecycleEventArgs $args)
    {
        die('Something is being inserted!');
    }

}

但那不是全部......

第三,这个事件监听器将每次提升一个对象,无论它有什么类(类),都会持久存储到db。当然这不是你想要的。
第一个解决方案,只检查&#34;一种&#34;持久化的对象beign是从LifecycleEventArgs参数中检索实体并使用instanceof检查该类的正确性

<?php

namespace Nick\AlertBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;

class AvailabilityAlertListener
{

    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        if ($entity instanceof \Your\Bundle\Path\To\AvailabilityAlert) {
            /** do something **/
        }
    }

}

BUT

如果你只保留那种对象,你也可以自己创建一个不遵循事件监听器/订阅者背后的逻辑的服务,并且一旦持有AvailabilityAlert的对象,通过召回一个对象来做一些动作他的方法。

回到你的问题

  

但是,如何让createAction监听此事件?我是一个   有点失落所以任何建议都会欣赏。

现在您应该已经了解事件被触发&#34;自动&#34;将对象持久保存到DB后。

还有一条建议

我注意到你想要做

include 'uapi_cron_single.php';
AddFlightsAction($alert);

这不正确。在Symfony2中,您应该使用autoloadingnamespacing来&#34;包括&#34;其他文件中的类。

答案 1 :(得分:0)

我建议您调度自定义事件,然后创建自定义侦听器。在Symfony2文档中有一个很好的条目:http://symfony.com/doc/current/components/event_dispatcher/introduction.html

如果我错了,请纠正我,但是你创建的这个监听器是一个DoctrineListener。所以它将在任何实体prePersist事件上发布。因此,您需要确定您所需的实体是否持久化。但我不是百分百肯定。