Skip to content

Commit b2be5a4

Browse files
committed
[Messenger] Added a trait for synchronous query & command buses
1 parent bd21549 commit b2be5a4

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-0
lines changed

components/messenger.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,5 +298,14 @@ loop, the message bus will add a :class:`Symfony\\Component\\Messenger\\Stamp\\R
298298
stamp to the message envelopes and the :class:`Symfony\\Component\\Messenger\\Middleware\\SendMessageMiddleware`
299299
middleware will know it should not route these messages again to a transport.
300300

301+
Learn more
302+
----------
303+
.. toctree::
304+
:maxdepth: 1
305+
:glob:
306+
307+
/messenger
308+
/messenger/*
309+
301310
.. _blog posts about command buses: https://matthiasnoback.nl/tags/command%20bus/
302311
.. _SimpleBus project: http://simplebus.io

messenger.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,4 +928,12 @@ will give you access to the following services:
928928
#. ``messenger.sender.yours``: the sender;
929929
#. ``messenger.receiver.yours``: the receiver.
930930

931+
Learn more
932+
----------
933+
.. toctree::
934+
:maxdepth: 1
935+
:glob:
936+
937+
/messenger/*
938+
931939
.. _`enqueue's transport`: https://github.com/php-enqueue/messenger-adapter

messenger/handler_results.rst

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
.. index::
2+
single: Messenger; Getting results / Working with command & query buses
3+
4+
Getting results
5+
---------------
6+
7+
When a message is handled, the :class:`Symfony\\Component\\Messenger\\Middleware\\HandleMessageMiddleware`
8+
adds a :class:`Symfony\\Component\\Messenger\\Stamp\\HandledStamp` for each responding handler,
9+
which can be used to get their returned value:
10+
11+
.. configuration-block::
12+
13+
.. code-block:: php
14+
15+
use Symfony\Component\Messenger\MessageBusInterface;
16+
use Symfony\Component\Messenger\Stamp\HandledStamp;
17+
18+
$envelope = $messageBus->dispatch(SomeMessage());
19+
20+
// Get the last handled stamp and its returned value:
21+
$handledStamp = $envelope->last(HandledStamp::class);
22+
$handledStamp->getResult();
23+
24+
This assumes there is only one configured handler or that only the last handler
25+
result is relevant. But you can also get the stamps for all handlers:
26+
27+
.. configuration-block::
28+
29+
.. code-block:: php
30+
31+
use Symfony\Component\Messenger\MessageBusInterface;
32+
use Symfony\Component\Messenger\Stamp\HandledStamp;
33+
34+
$envelope = $messageBus->dispatch(SomeMessage());
35+
$handledStamps = $envelope->all(HandledStamp::class);
36+
37+
A :class:`Symfony\\Component\Messenger\\HandleTrait` also exists in order to ease
38+
leveraging a Messenger bus for synchronous needs.
39+
The :method:`Symfony\\Component\Messenger\\HandleTrait::handle` method ensures
40+
there is exactly one handler registered and returns its result.
41+
42+
Working with command & query buses
43+
----------------------------------
44+
45+
The Messenger component can be used in CQRS architectures where command & query
46+
buses are central pieces of the application.
47+
See Martin Fowler's `article about CQRS`_ to learn more and :doc:`how to configure multiple buses </messenger/multiple_buses>`.
48+
49+
As queries are usually synchronous and expect to be handled once, getting the
50+
result from the handler is a common need.
51+
52+
You can directly leverage the ``HandleTrait`` trait in an action (or any caller):
53+
54+
.. configuration-block::
55+
56+
.. code-block:: php
57+
58+
use App\Message\ListItemsQuery;
59+
use App\MessageHandler\ListItemsQueryResult;
60+
use Symfony\Component\Messenger\HandleTrait;
61+
use Symfony\Component\Messenger\MessageBusInterface;
62+
63+
class ListItemsAction
64+
{
65+
use HandleTrait;
66+
67+
public function __construct(MessageBusInterface $messageBus)
68+
{
69+
$this->messageBus = $messageBus;
70+
}
71+
72+
public function __invoke(Request $request)
73+
{
74+
// Extract data from the request
75+
//...
76+
77+
$result = $this->query(new ListItemsQuery(/* ... */));
78+
79+
// Return a response with result
80+
// ...
81+
}
82+
83+
// Creating such a method is optional, but allows type-hinting the result
84+
private function query(ListItemsQuery $query): ListItemsResult
85+
{
86+
return $this->handle($query);
87+
}
88+
}
89+
90+
Or you can use the trait to create command & query buses classes.
91+
Here is how you can create a ``QueryBus`` class to inject in places you need
92+
a query bus behavior instead of the ``MessageBusInterface``:
93+
94+
.. configuration-block::
95+
96+
.. code-block:: php
97+
98+
namespace App\MessageBus;
99+
100+
use Symfony\Component\Messenger\Envelope;
101+
use Symfony\Component\Messenger\HandleTrait;
102+
use Symfony\Component\Messenger\MessageBusInterface;
103+
104+
class QueryBus
105+
{
106+
use HandleTrait;
107+
108+
public function __construct(MessageBusInterface $messageBus)
109+
{
110+
$this->messageBus = $messageBus;
111+
}
112+
113+
/**
114+
* @param object|Envelope $command
115+
*
116+
* @return mixed The handler returned value
117+
*/
118+
public function query($query)
119+
{
120+
return $this->handle($query);
121+
}
122+
}
123+
124+
.. _article about CQRS: https://martinfowler.com/bliki/CQRS.html

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy