CommandBus
![Software License][ico-license]
![Total Downloads][ico-downloads], (*1)
This a CommandBus implementation for php5.3. It's based on illuminate/events. This though will require a few other packages: illuminate/support, illuminate/contracts, and illuminate/container., (*2)
A CommandBus allows you to leverage commands and domain events in your php projects., (*3)
Essentially, the value add is to replace lines and lines of procedural style code in a class or method, with classes that do one thing.
These classes are loosely coupled together through eventing initiated by the CommandBus and CommandHandlers., (*4)
The usage shown below is the best explanation., (*5)
Install
Via Composer, (*6)
``` bash
$ composer require robrogers3/commandbus, (*7)
## Usage
### Requirements:
You have an app which uses illimunate packages. Especially illimunate/events.
### Your Goal:
Have a way to accomplish some task which takes many subtasks.
Perhaps currently you have the subtasks inside one class or even just one method. Some kind of God Object.
### The Solution:
Use a command bus to kick off (dispatch) the necessary classes to complete accomplish what was done in one place.
### Initial Setup:
You need to create a boot method or function that initialize the illuminate Container (IOC).
This method should:
* Register the container.
* Create an INSTANCE of the illimunate/event dispatcher.
* Register all the listeners for your events.
** The listeners can be fully written out, like 'Acme\UserHasRegistered'. Or better, 'Acme.*' The latter can catch all events prefixed by Acme
1. Define your listeners
``` php
$listeners = array(
'Acme\SendWelcomeEmail',
'Acme\AddToLdap',
'Acme\ConfigurePermissions'
);
- In your boot method, register them:
App::instance('Dispatcher', $dispatcher);
$listeners = getAppListeners();
foreach ($listeners as $listener) {
$dispatcher->listen('App.*', $listener);
}
Get to Work
1) Create your command. It's a simple class, a DTO of sorts. This is what gets thrown into the commandbus. Here is a simple one, (*8)
``` php
namespace Acme;, (*9)
class RegisterUserCommand
{
public $username;, (*10)
public function __construct($username)
{
$this->username = $username;
}
}, (*11)
2) Next, lets create a listener, like:
```php
namespace Acme;
use RobRogers\CommandBus\Eventing\EventListener;
class SendWelcomeEmail extends EventListener
{
public function whenUserHasRegistered(UserWasRegistered $event)
{
dump( 'Sending mail to ' . $event->user->username);
}
}
3) Create your command handler. The commandbus calls the handle method on this class., (*12)
namespace Acme;
use RobRogers\CommandBus\CommandHandler;
class UserRegisterCommandHandler implements CommandHandler
{
/**
* @var EventDispatcher
*/
private $dispatcher;
/**a
* @var EventGenerator
*/
private $eventGenerator;
/**
* @param EventDispatcher $dispatcher
* @param EventGenerator $eventGenerator
*/
public function __construct(EventDispatcher $dispatcher, EventGenerator $eventGenerator)
{
$this->dispatcher = $dispatcher;
$this->eventGenerator = $eventGenerator;
}
public function handle(/* user registered command */ $command)
{
$event = new Acme\UserHasRegistered($command);
$this->eventGenerator->register($event); //you can register many events
}
}
4) Finally create the 'event' we are listening for. This also a DTO, which contains the above UserRegister $command., (*13)
namespace Acme;
/**
* I am THE EVENT
* the command data get's shoved inside me. like $this->user->username
*/
class UserHasRegisteredEvent
{
public $user;
/** @var UserRegister $user */
public function __construct($user)
{
$this->user = $user;
}
}
5) Use it:, (*14)
$command = new RegisterUserCommand("Rob Rogers");
/** @var \RobRogers\CommandBus\BaseCommandBus $commandBus */
$commandBus = App::Make('\RobRogers\CommandBus\BaseCommandBus');
$commandBus->execute($command);
6) See what happens:, (*15)
If you have registered the three listeners above, they all get fired.
* send a welcome email to the user.
* add them to ldap (or wherever)
* configure their system permissions, (*16)
Bottom line in your controller, or wherever.
You just need 3 lines:
* instantiate the command.
* make the command bus.
* call the execute method., (*17)
For the three tasks above, it's not a big deal to call them directly. But if you have many many things to do, then it cleans things up rather nicely., (*18)
Change log
Please see CHANGELOG for more information what has changed recently., (*19)
Testing
bash
$ composer test, (*20)
Contributing
Please see CONTRIBUTING and CONDUCT for details., (*21)
Security
If you discover any security related issues, please email robrogers@me.com instead of using the issue tracker., (*22)
Credits
License
The MIT License (MIT). Please see License File for more information., (*23)