Проблемы с приемником событий Symfony2

0

с небольшим количеством проблем с пониманием слушателей событий. У меня есть следующее действие в моем контроллере

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

}

У меня нормальная форма (не построитель форм), и я создаю предупреждение из данных и отправляю их в свою базу данных. В случае успеха сообщение "Успешное" отправляется обратно на мой 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 ответа

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. Конечно, это не то, что вы хотите.
Первым решением для проверки только "вид" объекта beign persisted является извлечение объекта из аргумента 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 **/
        }
    }

}

НО

Если вы упорствуете только на этом объекте, вы также можете создать службу самостоятельно, чтобы не следовать логике прослушивателя событий/подписчиков и, когда-то сохраняя объект AvailabilityAlert, выполните некоторые действия, вызвав один из его методов.

Возвращаясь к вашему вопросу

Но как я могу заставить createAction прослушать это событие? Я немного потерян, поэтому любой совет ценит.

теперь вы должны понимать, что событие запускается "автоматически" после того, как объект сохраняется в БД.

Еще один совет

Я заметил, что вы хотите сделать

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

это не правильно. В Symfony2 вы должны использовать автозагрузку и namespacing для включения классов из других файлов.

  • 0
    Спасибо за фантастическое объяснение, определенно имейте более ясное понимание. Мне было интересно, что при добавлении предупреждения в базу данных действие postPersist, которое мне нужно сделать, связано с предупреждением. Так есть ли способ передать этот объект оповещения в функцию postPersist?
  • 1
    Из моего примера у вас уже есть доступный $entity = $args->getEntity();
0

Я бы предложил вам отправить пользовательское событие, а затем создать пользовательский прослушиватель. В документах Symfony2 есть хорошая запись об этом: http://symfony.com/doc/current/components/event_dispatcher/introduction.html

Исправьте меня, если я ошибаюсь, но этот слушатель, который вы создали, является DoctrineListener. Таким образом, он будет запущен на любом элементе prePersist. Поэтому вам нужно будет определить, сохраняется ли сущность, которая вам нужна. Но я не уверен на 100%.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню