2016年11月11日 星期五

Laravel 5.0 - Events & Handlers

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:
 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:
 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 handlemethod. 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.

from : https://mattstauffer.co/blog/laravel-5.0-events-and-handlers

沒有留言:

wibiya widget