Як налаштувати поведінку методу, не використовуючи наслідування

Дата оновлення перекладу 2022-11-20

Як налаштувати поведінку методу, не використовуючи наслідування

Дії до чи одразу після виклику методу

Якщо ви хочете зробити щось прямо перед або одразу після того, як викликано метод, ви можете відповідно оголосити подію на початку або наприкінці методу:

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)
    {
        // оголосити подію перед методом
        $event = new BeforeSendMailEvent($subject, $message);
        $this->dispatcher->dispatch('mailer.pre_send', $event);

        // отримати $foo і $bar з події, вони могли бути змінені
        $subject = $event->getSubject();
        $message = $event->getMessage();

        // справжня реалізація методу тут
        $ret = ...;

        // зробити щось після методу
        $event = new AfterSendMailEvent($ret);
        $this->dispatcher->dispatch('mailer.post_send', $event);

        return $event->getReturnValue();
    }
}

У цьому прикладі, оголошуються дві події:
#. mailer.pre_send до виконання методу, #. mailer.post_send - після.

Кожна з них використовує користувацький клас події, щоб передати інформацію слухачам двох подій. Наприклад, 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\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;
    }
}

А 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\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;
    }
}

Обидві події дозволяють вам отримати деяку інформацію (наприклад, getMessage()) і навіть змінити її (наприклад, setMessage()).

Тепер ви можете створювати підписника подій, що підключається до цієї події. Наприклад, ви можете слухати подію 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 Symfony\Component\EventDispatcher\EventSubscriberInterface;
use App\Event\AfterSendMailEvent;

class MailPostSendSubscriber implements EventSubscriberInterface
{
    public function onMailerPostSend(AfterSendMailEvent $event)
    {
        $ret = $event->getReturnValue();
        // змінити початкове знначення ``$ret``

        $event->setReturnValue($ret);
    }

    public static function getSubscribedEvents()
    {
        return array(
            'mailer.post_send' => 'onMailerPostSend'
        );
    }
}

Ось і все! Ваш підписник повинен бути викликаний автоматично (або прочитайте більше про конфігурацію підписника подій ).