Laravel 5.0 - Events & Handlers

Posted on January 21, 2015

Warning: This post is over a year old. I don't always update old posts with new information, so some of this information may be out of date.

If you haven't read it yet, go read the Laravel 5.0 - Commands & Handlers post. It'll give much-needed background for this article.

With Laravel 5's Commands (and their handlers), you can, in a simple, direct, and encapsulated way, emit a command to the system. DoThis. HandleACommandThatIsTellingMeToDoThis. It's imperative. It's telling the system what to do.

But sometimes, either as a result of a command, or just in another context, we want to send out a much more abstract notification. You've likely seen that Laravel 4 could trigger events based on a string event name:

    $response = Event::fire('auth.login', array($user));

This is sending a notice out to the world of the application: "Hey! Someone logged in! Do whatever you want with this information" It's informative. If you're familiar with the concept of PubSub, that's what going on with events.

Well, in Laravel 5, the eventing system has been upgraded and it looks a lot more like the command system we saw in the last post. Rather than identifying an event based on a string (auth.login), we're actually creating a PHP object and emitting that.

Sample

So, let's try it out.

Generate event

php artisan make:event ThingWasDone

... and that generates this:

<?php namespace SaveMyProposals\Events;

use SaveMyProposals\Events\Event;

use Illuminate\Queue\SerializesModels;

class ThingWasDone extends Event {

    use SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

}

You can attach data to this object by adding constructor parameters and setting them as properties of the class.

Generate event handler

You then create a handler:

php artisan handler:event SendMailInSomeParticularContext --event="ThingWasDone"

... which generates this:

<?php namespace SaveMyProposals\Handlers\Events;

use SaveMyProposals\Events\ThingWasDone;

use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldBeQueued;

class SendMailInSomeParticularContext {

    /**
     * Create the event handler.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  ThingWasDone  $event
     * @return void
     */
    public function handle(ThingWasDone $event)
    {
        //
    }

}

Note that the generator has already type-hinted a ThingWasDone $event parameter in the handle method. You can also use dependency injection, either in the constructor or in the handle method, to bring in whatever other tools you need to get this event handled.

Bind the events

Note that just creating an event and its handler doesn't inform the bus that they should be paired together. You need to bind the listening relationship in app\Providers\EventServiceProvider, on its $listen property:

// app\Providers\EventServiceProvider
    $listen = [
        ThingWasDone::class => [
            SendMailInSomeParticularContext::class,
            SaveSomeRecordInSomeOtherContext::class,
            DoSomethingElseInResponseToThingBeingDone::class
        ]
    ];

As you can see, you're using ::class to get a string representation of this event's class name, and then you're adding listeners (using ::class as well).

Ready, aim, ::fire

OK, so it's finally time to trigger the event. Note that these are just simple PHP classes--you could instantiate an Event manually, and instantiate its Handler, and pass the Event to the handler method. But the Laravel-provided bus makes it easier, more consistent, and more global:

\Event::fire(new ThingWasDone($param1, $param2));

That's it!

ShouldBeQueued

Just like with Commands, you can have your Event implement the Illuminate\Contracts\Queue\ShouldBeQueued interface, and that'll make the handling of the event be pushed up on the queue; and you can add the Illuminate\Queue\InteractsWithQueue trait to give easy access to methods for handling interactions with the queue like deleting the current job.

SerializesModels trait

Note that, like in commands, if you want to attach an Eloquent model to an event, you should include the SerializesModels trait at the top of the class definition for that event. At the time of this writing, it's actually already included by default.

Concluditation

That's it! Once you understand commands and handlers in Laravel 5, events are simple: the triggering system is informing the surrounding world that something happened, rather than demanding that the surrounding world do something. But they're both means of encapsulating the intent of a message, and they can play very nicely together, too.


Comments? I'm @stauffermatt on Twitter


Tags: laravel  •  events  •  5.0  •  laravel 5


(This is part of a series of posts on New Features in Laravel 5.0. )

  1. Sep 10, 2014 | laravel, 5.0, laravel 5
    In creating FormRequest, Taylor separated out both an interface (ValidatesWhenResolved) and a trait (ValidatesWhenResolvedTra...
  2. Sep 10, 2014 | laravel, 5.0, laravel 5
    Laravel 5.0 Laravel 5.0 is coming out in November, and there are a lot of features that have folks excited. The New Directory...
  3. Sep 12, 2014 | laravel, laravel 5, 5.0
    One of the big reasons Laravel 4.3 got moved to 5.0 is because the directory structure can seem like a big shift in thinking....
  4. Sep 20, 2014 | laravel, 5.0, laravel 5
    Performance optimization within our PHP code isn't always something at the forefront of our minds, but our backend code--espe...
  5. Sep 28, 2014 | laravel, laravel 5, 5.0
    In Laravel 5, you can now use the same Filesystem class which previously simplified interactions with the local filesystem, a...
  6. Sep 30, 2014 | laravel, 5.0, laravel 5
    Laravel 5.0 introduces the ability for the Container to resolve depencies injected into any methods that are resolved by the ...
  7. Oct 9, 2014 | laravel, 5.0, laravel 5
    Note: Route Annotations were eventually removed from core, and separated to a package maintained by the Laravel Community. T...
  8. Oct 10, 2014 | laravel, 5.0, laravel 5
    If you've been following along with my previous blog posts about Laravel 5.0, you may have noticed that route filters were fi...
  9. Oct 10, 2014 | laravel, 5.0, laravel 5
    Note: Event Annotations were eventually removed from core, and separated to a package maintained by the Laravel Community. T...
  10. Oct 16, 2014 | laravel, 5.0, laravel 5
    If you've followed my blog for a while, you've probably seen me struggle with Laravel's environment detection--especially reg...
  11. Nov 20, 2014 | laravel, 5.0, laravel 5
    Eric Barnes has a longer write up on this, so I'll just keep it short: Laravel 5.0 is introducing a pretty incredible cron-st...
  12. Jan 2, 2015 | laravel, 5.0, commands, laravel 5
    As you’ve probably read me mention on Twitter, I’ve paused on blogging new Laravel 5 features to try to give Taylor some ...
  13. Jan 16, 2015 | laravel, laravel 5
    It's very simple to get started in a new Laravel 5 app: composer create-project laravel/laravel my-project-name-here dev-deve...
  14. Jan 19, 2015 | laravel 5, laravel
    You might be missing the "prettier" Whoops error handler from Laravel 4. If so, here's how to bring it back. Updat...
  15. Jan 21, 2015 | laravel, events, 5.0, laravel 5
    If you haven't read it yet, go read the Laravel 5.0 - Commands & Handlers post. It'll give much-needed background for th...
  16. Jan 26, 2015 | laravel, laravel 5
    Sometimes it can seem like a lot of work to create an event, create its handler, and bind the two. Create a command, create i...
  17. Feb 1, 2015 | laravel, laravel 5
    When you wanted to customize your error pages—for example, showing a particular cat GIF when your users hit a 404—you’d...
  18. Feb 14, 2015 | laravel 5, laravel, eloquent
    I had completely forgotten to finish my Laravel 5.0 blog posts, but I saw a great quick introduction to attribute casting at ...

Subscribe

For quick links to fresh content, and more thoughts that don't make it to the blog