Получение результатов из вашего обработчика

Дата обновления перевода 2024-07-25

Получение результатов из вашего обработчика

Когда сообщение обрабатывается, HandleMessageMiddleware добавлет HandledStamp для каждого объекта, который обрабатывал сообщение. Вы можете использовать это, чтобы получить значение, возвращенное обработчиком(ами):

1
2
3
4
5
6
7
8
9
10
11
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Stamp\HandledStamp;

$envelope = $messageBus->dispatch(new SomeMessage());

// получить значение, которое было возвращено последним обработчиком сообщения
$handledStamp = $envelope->last(HandledStamp::class);
$handledStamp->getResult();

// или получить информацию обо всех других обработчиках
$handledStamps = $envelope->all(HandledStamp::class);

Работа с автобусами команд и запросов

Компонент Messenger может быть использован в CQRS-архитектурах, где автобусы команд и запросов являются центральными элементами приложения. Прочтите статью о CQRS от Мартина Фоулера, чтобы узнать больше, и о том, как сконфигурировать несколько автобусов.

Так как запросы обычно являются синхронными и чаще всего обрабатываются единожды, получение результатов из обработчика - распространенная потребность.

HandleTrait существует для получения результата обработчика при синхронной обработке. Он также гарантирует, что будет зарегистрирован только один обработчик. HandleTrait может быть использован в любом классе, который имеет свойство $messageBus:

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
// src/Action/ListItems.php
namespace App\Action;

use App\Message\ListItemsQuery;
use App\MessageHandler\ListItemsQueryResult;
use Symfony\Component\Messenger\HandleTrait;
use Symfony\Component\Messenger\MessageBusInterface;

class ListItems
{
    use HandleTrait;

    public function __construct(
        private MessageBusInterface $messageBus,
    ) {
    }

    public function __invoke(): void
    {
        $result = $this->query(new ListItemsQuery(/* ... */));

        // сделайте что-то с результатом
        // ...
    }

    // Создание такого метода необязательно, но позволяет добавлять подсказки в результат
    private function query(ListItemsQuery $query): ListItemsQueryResult
    {
        return $this->handle($query);
    }
}

Таким образом, вы можете использовать это качество для создания классов автобусов команд и запросов. Например, вы можете создать специальный класс QueryBus, и внедрить его там, где вам нужно поведение автобуса запросов, вместо MessageBusInterface:

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
// src/MessageBus/QueryBus.php
namespace App\MessageBus;

use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\HandleTrait;
use Symfony\Component\Messenger\MessageBusInterface;

class QueryBus
{
    use HandleTrait;

    public function __construct(
        private MessageBusInterface $messageBus,
    ) {
    }

    /**
     * @param object|Envelope $query
     *
     * @return mixed The handler returned value
     */
    public function query($query): mixed
    {
        return $this->handle($query);
    }
}