Как я могу запустить метод публикации после запуска события?

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

use Symfony\Contracts\EventDispatcher\Event;

class CaseEvent extends Event
{
    public const NAME = 'case.event';

    // ...
}

И я создал подписчика следующим образом:

use App\Event\CaseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class CaseEventListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [CaseEvent::NAME => 'publish'];
    }

    public function publish(CaseEvent $event): void
    {
        // do something
    }
}

Я также определил следующее в services.yaml:

App\EventSubscriber\CaseEventListener:
  tags:
    - { name: kernel.event_listener, event: case.event}

Почему при отправке такого события метод прослушивателя publish() никогда не выполняется?

/**
 * Added here for visibility but is initialized in the class constructor
 *
 * @var EventDispatcherInterface
 */
private $eventDispatcher;

$this->eventDispatcher->dispatch(new CaseEvent($args));

Я подозреваю, что проблема в kernel.event_listener, но не знаю, как правильно подписать слушателя на событие.


person ReynierPM    schedule 27.08.2019    source источник
comment
@yivi Я могу ошибаться, но мне нужно иметь разные классы, подписанные на событие, в этом сценарии CaseEvent и запускать разные методы, например, в этом случае publish() не так, как это работает? Или я все неправильно понимаю?   -  person ReynierPM    schedule 27.08.2019
comment
Разве у нас не возник этот вопрос? dispatch (new CaseEvent ($ args) вызовет событие с именем App \ Event \ CaseEvent, а не case.event. И нет причин добавлять конфигурацию для подписчика.   -  person Cerad    schedule 27.08.2019
comment
@Cerad, чего я здесь не вижу? Даже удаление конфигурации подписчика не выполняет метод publish. @yivi уже обсуждал это на канале Symfony Slack, см. github.com/symfony/symfony/blob/4.3/src/Symfony/Component/ параметр не является обязательным. Позже сегодня я буду работать над документами, добавив примечание;)   -  person ReynierPM    schedule 27.08.2019
comment
В основном это дубликат: stackoverflow.com/questions/57540654/ И чего вам не хватает, так это того, что метод отправки использует имя класса события в качестве имени события, если только вы не передадите явное имя события в качестве второго аргумента. Это довольно недавнее изменение. bin / console debug: может помочь диспетчер событий.   -  person Cerad    schedule 27.08.2019
comment
Также документы не полностью догнали 4.3. Эта статья может помочь объяснить, что изменилось и что происходит: symfony.com/blog/new-in-symfony-4-3-simpler-event-dispatching   -  person Cerad    schedule 27.08.2019
comment
Либо вы передаете параметр; или вы подписываетесь на имя класса fq. В своем ответе я использовал последнее; поскольку это более современный подход. Но последнее тоже сработало бы.   -  person yivi    schedule 27.08.2019


Ответы (1)


Измените подписчика так, чтобы getSubscribedEvents() читался так:

public static function getSubscribedEvents(): array
{
    return [CaseEvent::class => 'publish'];
}

При этом используются преимущества изменений в 4.3; где вам больше не нужно указывать имя события, и упрощает диспетчеризацию, которую вы используете (диспетчеризация объекта события сама по себе и опускание имени события).

Вы также могли оставить своего подписчика как есть; и измените вызов диспетчеризации на «старый стиль»:

$this->eventDispatcher->dispatch(new CaseEvent($args), CaseEvent::NAME);

Также удалите теги event_listener из services.yaml. Поскольку вы реализуете EventSubscriberInterface, вам не нужно добавлять какую-либо другую конфигурацию.

person yivi    schedule 27.08.2019