简体   繁体   中英

Symfony2 Event Listener Issues

having a bit of trouble understanding Event Listeners. I have the following action in my controller

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

}

I have a normal form (not form builder) and I create an Alert from the data and send it to my database. If successful, a Success message is sent back to my ajax.

Here's the problem. If the createAction is successful, I need it to send the alert to another class and do some stuff with it. So it was suggested that an Event Listener could do this for me. So I created a listener to test

<?php

namespace Nick\AlertBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;

class AvailabilityAlertListener
{

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

}

I then added it to services.yml

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

But then how do I make the createAction listen for this event? I am a bit lost so any advice appreciate. Essentially, at the end of createAction, I want to do something like

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

But I dont want to do it like the above because it is messy. But if createAction is successful, I need the alert to be sent to another class, so whats the best way to do this?

Thanks

First of all when you define a service without parameters you don't have to specify arguments: [] , you could simply write that

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

Second, do you know that event will be fired before entity is persisted? I suppose that's not what you want (I suppose) as you were writing about trigger an event after object is inserted into DB. So you should modify your service definition as follows

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

and your service class

<?php

namespace Nick\AlertBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;

class AvailabilityAlertListener
{

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

}

But that's not all ...

Third, this event listener will be raised every time an object, no matter what kind (class) it has , is persisted to db. Of course this is not what you want to.
First solution to check only for "a kind" of object beign persisted is to retrieve entity from LifecycleEventArgs argument and check with instanceof for correctness the class

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

If you persist that kind of object only there you could also create a service on your own that not follows the logic behind event listener/subscribers and, once persisted an object of AvailabilityAlert , do some action by recalling one of his methods.

Returning to your question

But then how do I make the createAction listen for this event? I am a bit lost so any advice appreciate.

now you should have understood that event is triggered "automatically" after object is persisted to DB.

One more advice

I've noticed that you want to do

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

that's not correct. In Symfony2 you should use autoloading and namespacing to "include" classes from other files.

I would suggest you dispatch custom event and then create custom listener. In Symfony2 docs there is nice entry about it: http://symfony.com/doc/current/components/event_dispatcher/introduction.html

Correct me if i'm wrong, but this listener which you have created is an DoctrineListener. So it will be launched on ANY entity prePersist event. So you would need to determine if entity that you need is persisted. But i'm not 100% sure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM