symfony 5 - event not being dispatched

1.8k views Asked by At

I use an event subscriber to handle some actions when my order form is submitted.

Problem my event is not being dispached but symfony is able to find him because he tells me that my OrderEvent::ORDER_CREATE is orphan.

I excpected that execution was stopped with die('Hello you from subscriber'); but it's not.

Controller

public function commanderPanierAction(Request $request, SelectionWeb $selectionWeb, TableLumineuse $tableLumineuse, EventDispatcherInterface $eventDispatcher)
{
    // DO PREVIOUS STUFF

    $Order = new Order();
    $OrderForm = $this->createForm(OrderForm::class, $Order);
        
    if ($request->isMethod('POST')) {
      $OrderForm->handleRequest($request);

      if ($OrderForm->isSubmitted() && $OrderForm->isValid()) {
          // OrderForm is valid proceed
          $eventDispatcher->dispatch(
              new OrderEvent($Order),
              OrderEvent::ORDER_CREATE
          );
      }
   } 

OrderEvent

<?php

namespace App\Event;

use App\Entity\Order;
use Symfony\Contracts\EventDispatcher\Event;

class OrderEvent extends Event
{
    public const ORDER_CREATE = 'order.created';

    protected $order;

    public function __construct(Order $order)
    {
        $this->order= $order;
    }

    public function getOrder(): Order
    {
        return $this->order;
    }
}

OrderSubscriber

<?php

namespace App\EventSubscriber;

use App\Event\CommandeWebEvent;
use App\Service\SelectionWeb\SelectionWeb;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;


class OrderSubscriber implements EventSubscriberInterface
{
    private $entityManager;

    private $selectionWeb;

    public function __construct(EntityManagerInterface $entityManager, SelectionWeb $selectionWeb)
    {
        $this->entityManager = $entityManager;
        $this->selectionWeb = $selectionWeb;
    }

    public static function getSubscribedEvents()
    {
        return [
            OrderEvent::ORDER_CREATE => [
                // The higher the number, the earlier the method is called.
                ['processOrder', 10],
                ['notifyOrder', -10]
            ]
        ];
    }

    public function processOrder(OrderEvent $event)
    {
        // TODO
        die('Hello you from subscriber');
    }

    public function notifyOrder(OrderEvent $event)
    {
        // TODO
    }
}

EDIT

The only workaround found (thx to @nikserg) is to inject subscriber into controller action (subscriber has dependencies) then register my subscriber as service in services.yaml finaly use $eventDispatcher->addSubscriber($subscriber); before $eventDispatcher->dispatch(new OrderEvent($Order),OrderEvent::ORDER_CREATE);

It seems all that stuff is really complex for a task as simple as that

EDIT2

I found an another way I'm able to execute my subscriber without usage of $eventDispatcher->addSubscriber($subscriber); and only with $eventDispatcher->dispatch(new OrderEvent($Order)); only if I configure my subscriber as service in services.yaml but why symfony does need this information in services.yaml ? Thought that everything in src/ is avaible to be used as service..

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
    resource: '../src/*'
    exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

# If I add those It works
App\EventSubscriber\OrderSubscriber:
    autowire: true

EDIT3

My OrderSubscriber is loaded into container so why I should set it explicitly to being execute ? I can't figure out what's going on

php bin/console debug:container
---------------------------------------- ---------------------------------------
Service ID                               Class name
---------------------------------------- ----------------------------------------
App\EventSubscriber\OrderSuscriber App\EventSubscriber\OrderSuscriber

EDIT 4

If I set my OrderSubscriber explicitly there is two instances of it into container. Why symfony execute one set explicitly and not the one set with resource: '../src/*'

2

There are 2 answers

0
akio On BEST ANSWER

First I want to thank you all for your time and let me apologize my problem was due to a typo I wrote OrderSuscriber instead of OrderSubscriber that's why there was 2 services into my container and why defined service explicitly was working.

10
nikserg On

Symfony will autowire your subscriber as service, if you will require it as argument in action:

public function commanderPanierAction(Request $request, SelectionWeb $selectionWeb, TableLumineuse $tableLumineuse, OrderSubscriber $orderSubscriber)

Of course, if your subscriber is registered properly.

But let me advice you not to create subscribers as objects manually. The main good thing about subscribers is that you know nothing about them, when you fire event. There could be dozens of subscribers to this event, and all of them will proceed your event. That will keep your code nice and lower cohesion.

It's in docs: https://symfony.com/doc/current/event_dispatcher.html#creating-an-event-subscriber