|
| 1 | +--- |
| 2 | +currentMenu: command_bus_bundle |
| 3 | +--- |
| 4 | + |
| 5 | +# Command bus bundle |
| 6 | + |
| 7 | +Using the building blocks supplied by the [SimpleBus/MessageBus library](https://github.com/SimpleBus/MessageBus) you |
| 8 | +can create a command bus, which is basically a message bus, with some middlewares and a map of message handlers. This is |
| 9 | +described in the [documentation of MessageBus](http://simplebus.github.io/MessageBus/doc/command_bus.html). |
| 10 | + |
| 11 | +If you use Symfony, you don't have to manually configure a command bus in each project. The [SimpleBus/SymfonyBridge |
| 12 | +library](https://github.com/SimpleBus/SymfonyBridge) comes with the `SimpleBusCommandBusBundle` which handles it for |
| 13 | +you. |
| 14 | + |
| 15 | +First enable the bundle in your application's kernel: |
| 16 | + |
| 17 | +```php |
| 18 | +class AppKernel extends Kernel |
| 19 | +{ |
| 20 | + public function registerBundles() |
| 21 | + { |
| 22 | + $bundles = array( |
| 23 | + ... |
| 24 | + new SimpleBus\SymfonyBridge\SimpleBusCommandBusBundle() |
| 25 | + ) |
| 26 | + ... |
| 27 | + } |
| 28 | + ... |
| 29 | +} |
| 30 | +``` |
| 31 | + |
| 32 | +## Using the command bus |
| 33 | + |
| 34 | +This bundle provides the `command_bus` service which is an instance of `SimpleBus\Message\Bus\MessageBus`. Wherever you |
| 35 | +like, you can let it handle commands, e.g. inside a container-aware controller: |
| 36 | + |
| 37 | +```php |
| 38 | +// $command is an arbitrary object that will be passed to the command handler |
| 39 | +$command = ...; |
| 40 | + |
| 41 | +$this->get('command_bus')->handle($command); |
| 42 | +``` |
| 43 | + |
| 44 | +However, you are encouraged to properly inject the `command_bus` service as a dependency whenever you need it: |
| 45 | + |
| 46 | +```yaml |
| 47 | +services: |
| 48 | + some_service: |
| 49 | + arguments: |
| 50 | + - @command_bus |
| 51 | +``` |
| 52 | + |
| 53 | +## Registering command handlers |
| 54 | + |
| 55 | +As described in the [MessageBus documentation](http://simplebus.github.io/MessageBus/doc/command_bus.html) you can |
| 56 | +delegate the handling of particular commands to command handlers. This bundle allows you to register your own |
| 57 | +command handlers by adding the `command_handler` tag to the command handler's service definition: |
| 58 | + |
| 59 | +```yaml |
| 60 | +services: |
| 61 | + register_user_command_handler: |
| 62 | + class: Fully\Qualified\Class\Name\Of\RegisterUserCommandHandler |
| 63 | + tags: |
| 64 | + - { name: command_handler, handles: Fully\Qualified\Class\Name\Of\RegisterUser } |
| 65 | +``` |
| 66 | +
|
| 67 | +### Auto-Register command handlers |
| 68 | +
|
| 69 | +You can omit the `handles` tag attribute if your handler meets the following conditions: |
| 70 | + |
| 71 | +1. Uses the "class_based" command name resolving strategy |
| 72 | +2. Handles a single command using the `__invoke` method |
| 73 | +3. Has a single, non optional class type hinted `__invoke` method parameter |
| 74 | + |
| 75 | +> #### Command handlers are lazy-loaded |
| 76 | +> |
| 77 | +> Since only one of the command handlers is going to handle any particular command, command handlers are lazy-loaded. |
| 78 | +> This means that their services should be defined as public services (i.e. you can't use `public: false` for them). |
| 79 | + |
| 80 | +> #### Command handlers are callables |
| 81 | +> |
| 82 | +> Any service that is a [PHP callable](http://php.net/manual/en/language.types.callable.php) itself can be used as a |
| 83 | +> command handler. If a service itself is not callable, SimpleBus looks for a `handle` method and calls it. If you want |
| 84 | +> to use a custom method, just add a `method` attribute to the `command_handler` tag: |
| 85 | +> |
| 86 | +> ```yaml |
| 87 | +> services: |
| 88 | +> register_user_command_handler: |
| 89 | +> ... |
| 90 | +> tags: |
| 91 | +> - { name: command_handler, handles: ..., method: registerUser } |
| 92 | +``` |
| 93 | + |
| 94 | +## Setting the command name resolving strategy |
| 95 | + |
| 96 | +To find the correct command handler for a given command, the name of the command is used. This can be either 1) its |
| 97 | +fully-qualified class name (FQCN) or, 2) if the command implements the `SimpleBus\Message\Name\NamedMessage` interface, |
| 98 | +the value returned by its static `messageName()` method. By default, the first strategy is used, but you can configure |
| 99 | +it in your application configuration: |
| 100 | + |
| 101 | +```yaml |
| 102 | +command_bus: |
| 103 | + # default value for this key is "class_based" |
| 104 | + command_name_resolver_strategy: named_message |
| 105 | +``` |
| 106 | +
|
| 107 | +When you change the strategy, you also have to change the value of the `handles` attribute of your command handler |
| 108 | +service definitions: |
| 109 | + |
| 110 | +```yaml |
| 111 | +services: |
| 112 | + register_user_command_handler: |
| 113 | + class: Fully\Qualified\Class\Name\Of\RegisterUserCommandHandler |
| 114 | + tags: |
| 115 | + - { name: command_handler, handles: register_user } |
| 116 | +``` |
| 117 | + |
| 118 | +Make sure that the value of `handles` matches the return value of `RegisterUser::messageName()`. |
| 119 | + |
| 120 | +## Adding command bus middleware |
| 121 | + |
| 122 | +As described in the [MessageBus documentation](http://simplebus.github.io/MessageBus/doc/command_bus.html) you can |
| 123 | +extend the behavior of the command bus by adding middleware to it. This bundle allows you to register your own |
| 124 | +middleware by adding the `command_bus_middleware` tag to the middleware service definition: |
| 125 | + |
| 126 | +```yaml |
| 127 | +services: |
| 128 | + specialized_command_bus_middleware: |
| 129 | + class: YourSpecializedCommandBusMiddleware |
| 130 | + public: false |
| 131 | + tags: |
| 132 | + - { name: command_bus_middleware, priority: 100 } |
| 133 | +``` |
| 134 | + |
| 135 | +By providing a value for the `priority` tag attribute you can influence the order in which middlewares are added to the |
| 136 | +command bus. |
| 137 | + |
| 138 | +> #### Middlewares are not lazy-loaded |
| 139 | +> |
| 140 | +> Whenever you use the command bus, you also use all of its middlewares, so command bus middlewares are not lazy-loaded. |
| 141 | +> This means that their services should be defined as private services (i.e. you should use `public: false`). See also: |
| 142 | +> [Marking Services as public / |
| 143 | +> private](http://symfony.com/doc/current/components/dependency_injection/advanced.html#marking-services-as-public-private) |
| 144 | + |
| 145 | +## Logging |
| 146 | + |
| 147 | +If you want to log every command that is being handled, enable logging in `config.yml`: |
| 148 | + |
| 149 | +```yaml |
| 150 | +command_bus: |
| 151 | + logging: ~ |
| 152 | +``` |
| 153 | + |
| 154 | +Messages will be logged to the `command_bus` channel. |
0 commit comments