How to Customize a Method Behavior without Using Inheritance
Warning: You are browsing the documentation for Symfony 3.x, which is no longer maintained.
Read the updated version of this page for Symfony 7.1 (the current stable version).
Doing something before or after a Method Call
If you want to do something just before, or just after a method is called, you can dispatch an event respectively at the beginning or at the end of the method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
class CustomMailer
{
// ...
public function send($subject, $message)
{
// dispatch an event before the method
$event = new BeforeSendMailEvent($subject, $message);
$this->dispatcher->dispatch('mailer.pre_send', $event);
// get $foo and $bar from the event, they may have been modified
$subject = $event->getSubject();
$message = $event->getMessage();
// the real method implementation is here
$returnValue = ...;
// do something after the method
$event = new AfterSendMailEvent($returnValue);
$this->dispatcher->dispatch('mailer.post_send', $event);
return $event->getReturnValue();
}
}
In this example, two events are thrown: mailer.pre_send
, before the method is
executed, and mailer.post_send
after the method is executed. Each uses a
custom Event class to communicate information to the listeners of the two
events. For example, BeforeSendMailEvent
might look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
// src/AppBundle/Event/BeforeSendMailEvent.php
namespace AppBundle\Event;
use Symfony\Component\EventDispatcher\Event;
class BeforeSendMailEvent extends Event
{
private $subject;
private $message;
public function __construct($subject, $message)
{
$this->subject = $subject;
$this->message = $message;
}
public function getSubject()
{
return $this->subject;
}
public function setSubject($subject)
{
$this->subject = $subject;
}
public function getMessage()
{
return $this->message;
}
public function setMessage($message)
{
$this->message = $message;
}
}
And the AfterSendMailEvent
even like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// src/AppBundle/Event/AfterSendMailEvent.php
namespace AppBundle\Event;
use Symfony\Component\EventDispatcher\Event;
class AfterSendMailEvent extends Event
{
private $returnValue;
public function __construct($returnValue)
{
$this->returnValue = $returnValue;
}
public function getReturnValue()
{
return $this->returnValue;
}
public function setReturnValue($returnValue)
{
$this->returnValue = $returnValue;
}
}
Both events allow you to get some information (e.g. getMessage()
) and even change
that information (e.g. setMessage()
).
Now, you can create an event subscriber to hook into this event. For example, you
could listen to the mailer.post_send
event and change the method's return value:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// src/AppBundle/EventSubscriber/MailPostSendSubscriber.php
namespace AppBundle\EventSubscriber;
use AppBundle\Event\AfterSendMailEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MailPostSendSubscriber implements EventSubscriberInterface
{
public function onMailerPostSend(AfterSendMailEvent $event)
{
$returnValue = $event->getReturnValue();
// modify the original ``$returnValue`` value
$event->setReturnValue($returnValue);
}
public static function getSubscribedEvents()
{
return [
'mailer.post_send' => 'onMailerPostSend'
];
}
}
That's it! Your subscriber should be called automatically (or read more about event subscriber configuration).