Reputation: 1021
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/*'
Upvotes: 2
Views: 2172
Reputation: 1021
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.
Upvotes: 1
Reputation: 382
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
Upvotes: 1