So Laravel 5 was finally released yesterday with the final implementation of the command bus but I was wandering, what's the real difference in using a command bus over event mechanisms that we have in the previous releases?
Ok, I see the reason that it can be used to create commands from Request objects which is pretty useful but beyond that it seems to behave in a similar way even down to the whole queuing functionality for events now?
Can you please provide examples of use cases and where the pros and cons of either are?
Both are messages.They convey specific information; a command about the intent to do something, or an event about the fact that happened. From the computer's point of view, they are no different. Only the business logic and the interpretation of the message can find the difference between event and command.
Laravel's events provide a simple observer pattern implementation, allowing you to subscribe and listen for various events that occur within your application. Event classes are typically stored in the app/Events directory, while their listeners are stored in app/Listeners .
Laravel makes it very convenient to define the input you expect from the user using the signature property on your commands. The signature property allows you to define the name, arguments, and options for the command in a single, expressive, route-like syntax.
Events provide a simple observer implementation which allows a user to subscribe and listen to various events triggered in the web application. All the event classes in Laravel are stored in the app/Events folder and the listeners are stored in the app/Listeners folder.
The differences appear minor - but have some key differences.
Lets do an example to illustrate it best. Lets say we create a user, and we want to send them a welcome email and also update our newsletter list.
In a Command Scenario would would do
AdminController { function create() { Bus::dispatch(new CreateUser(Auth::user()); } }
then in our CommandClass - we would do
public function handle(CreateUser $auth) { // 1. Create the user here // 2. Send welcome email // 3. Update our newsletter }
But if we use events - we would do something like this in our CommandClass
public function handle(CreateUser $auth) { // 1. Create the user here Event::fire(new UserWasCreated($user)); }
then we can create as many events as we want to listen to that event and do something:
EventClassA
Event::listen('UserWasCreated', function($event) { // 2. Send welcome email });
EventClassB
Event::listen('UserWasCreated', function($event) { // 3. Update our newsletter });
The great thing is separation of concerns. The command "createuser" now does not need to worry itself about what happens after a user is created. It just needs to CreateUser.
Also - if we want to add another function after a user signs up - say enter them in a lotto draw - you can just add another Event Class and add a new event listener.
EventClassC
Event::listen('UserWasCreated', function($event) { // 4. Register them in lotto });
Notice how we didnt need to touch the command CreateUser class code at all? This provides a true separation concerns of classes in a OOP style approach.
I just want to share my understanding of this concept on top of the correct answer:
The main difference is that Commands can change a Model state, while Events just react to a state change.
COMMANDS:
Commands in Laravel represent the implementation of the Command design pattern.
The main adventages of Commands:
To create a Command in Laravel 5:
You need to generate a command DTO (which can implement the SelfHandling interface). Using php artisan make:command {command-name}
Example: php artisan make:command Course/PostCourseCommand
The naming convention for commands: speak the business language and add postfix Command to it
To call (dispatch) the command from you controller, you can use:
$this->dispatch(new PostCourseCommand())
or
Bus::dispatch(new PostCourseCommand());
Side Note: The "dispatch from request” feature is a nice way to skip passing the variables to the command constructor one by one, instead it will resolve this for you:
Example:
$test_request = Request::create('/test', 'GET', [ 'name' => 'Mahmoud', 'nickname' => 'Mega' ]); $result = Bus::dispatchFrom( CreateCourse::class, $test_request );
Finally:
You can separate the handler function and it’s logic from the command DTO to the Handlers directory, to do so:
art handler:command --command="Course/PoatCourseCommand"
EVENTS:
Events in Laravel represent the implementation of the Observer design pattern.
To create an Event in Laravel 5:
art make:event {event-name}
Example: art make:event LogSomething
art handler:event LogSomething --event="LogSomething"
(app/Providers/EventServiceProvider.php)
Example:
protected $listen = [ \Zzz\Events\LogSomething::class => [ // event.name \Zzz\Handlers\Events\LogSomething::class, //EventListener ], ],
To call (fire) an Event:
use:
Event::fire(New LogSomething());
or you can use the event helper
event(New LogSomething());
Side Note: alternatively you can generate an event by simply registering the event in the service provider then running this command.
php artisan event:generate
<< this will automatically add the two classes for you
Also you can listen to an event without creating an event handler or registering a lister in the listeners array, by just going to the event service prover and inside the boot function writing your event and its action (NOT RECOMMENDED). Example:
Event::listen('XXX\Events\DoSomethingElse', function($event) { dd('handle me :)'); });
Finally: you can queue an event or even subscribe to multiple events from within the class itself..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With