How to Customize a Method Behavior without Using Inheritance

Doing something before or after a Method Call

If you want to do something right before, or directly 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($event, 'mailer.pre_send');

        // get $subject and $message 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($event, 'mailer.post_send');

        return $event->getReturnValue();
    }
}

In this example, two events are dispatched:

この例では、2 つのイベントが送出されます。
  1. mailer.pre_send, before the method is called,
    メソッドが呼び出される前に、mailer.pre_send、
  2. and mailer.post_send after the method is called.
    メソッドが呼び出された後の mailer.post_send 。

Each uses a custom Event class to communicate information to the listeners of the two events. For example, BeforeSendMailEvent might look like this:

それぞれがカスタム Event クラスを使用して、2 つのイベントのリスナーに情報を伝達します。たとえば、BeforeSendMailEvent は次のようになります。
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/Event/BeforeSendMailEvent.php
namespace App\Event;

use Symfony\Contracts\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:

また、AfterSendMailEvent は次のようになります。
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/Event/AfterSendMailEvent.php
namespace App\Event;

use Symfony\Contracts\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()).

どちらのイベントでも、何らかの情報を取得したり (getMessage() など)、その情報を変更したりできます (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:

これで、このイベントにフックするイベント サブスクライバーを作成できます。たとえば、mailer.post_send イベントをリッスンして、メソッドの戻り値を変更できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// src/EventSubscriber/MailPostSendSubscriber.php
namespace App\EventSubscriber;

use App\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).

それでおしまい!サブスクライバーは自動的に呼び出されます (または、イベント サブスクライバーの構成に関する詳細を参照してください)。