с небольшим количеством проблем с пониманием слушателей событий. У меня есть следующее действие в моем контроллере
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 успешно, мне нужно, чтобы сообщение было отправлено в другой класс, так что лучший способ сделать это?
благодаря
Прежде всего, когда вы определяете сервис без параметров, вам не нужно указывать 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 для включения классов из других файлов.
Я бы предложил вам отправить пользовательское событие, а затем создать пользовательский прослушиватель. В документах Symfony2 есть хорошая запись об этом: http://symfony.com/doc/current/components/event_dispatcher/introduction.html
Исправьте меня, если я ошибаюсь, но этот слушатель, который вы создали, является DoctrineListener. Таким образом, он будет запущен на любом элементе prePersist. Поэтому вам нужно будет определить, сохраняется ли сущность, которая вам нужна. Но я не уверен на 100%.
$entity = $args->getEntity();