Eventing Overview Setup0:00
Okay, why don't we move on to a discussion about eventing. So we'll start, like we did with the scheduling lessons, with a review on basic eventing, how it works, how we listen for events, all of that good stuff. And then in the next video, we'll peel back the curtain and figure out how some of this stuff is orchestrated behind the scenes. Okay, so I'm at my EventServiceProvider. Real quick on that note though, if you want to go to it manually, you will go to App, Providers, EventServiceProvider. Or if you're using something like Sublime or PHPStorm, my recommendation, as always, is to keep that sidebar closed.
Or if you're using something like Sublime or PHPStorm, my recommendation, as always, is to keep that sidebar closed. So yeah, you could do this. You could type it in. But remember, tools like Sublime offer fussy searching. So if you want to go to EventServiceProvider, then you could type ESP. And that's what I would do. ESP, and you're there. Or if you want to go to your RouteServiceProvider, RSP, and we're there. That's way faster than browsing through a directory tree.
Or if you want to go to your RouteServiceProvider, RSP, and we're there. That's way faster than browsing through a directory tree. Okay, so anyways, at our EventServiceProvider, here's where you can register any mappings for both your events and your listeners. Now, quick note on this. I am currently using the DevMaster version of Laravel. So the directory structure you see here is how it will be reflected and represented in Laravel 5.1. Mostly it's the same, but there's a couple tiny tweaks. They're non-breaking. They're just naming conventions.
Events and Listeners Concept1:27
They're non-breaking. They're just naming conventions. For example, you won't see a commands or handlers directory in here. That can be a little technical. So instead, they've decided to be a little more Laravel-like, I'd say, and go with jobs, events, and listeners. Okay, so with that note out of the way, how does this work? Well, we can register that when this event occurs, remember, think of an event as an important thing that just took place in your application. The Laravel documentation uses things like User purchased Podcast.
remember, think of an Event as an important thing that just took place in your application. The Laravel documentation uses things like User purchased Podcast. So if you ever find yourself in a situation where you want to say, well, when this happens, I need to make sure we do this and this and this. Well, usually that's a perfect use case for firing an Event. And here's another example. At Laracasts, I can upgrade a User's subscription. When they take that action, that's an important Event that I need to respond to. Or another one is when I ban a User. Well, once again, when that happens,
so we should fire off an email to let them know they no longer are welcome on the site. But anyways, if we think about it, if you have five different things you need to do in response to an event, well, we are better following the single responsibility principle. If we take each of those tasks, we give them a readable class name, and then we call them one by one. So with that in mind, if we want to email a ban notification, well, maybe we could just write it out just like that. And further, here's a really cool thing. Yes, you can create your events and your listeners one at a time from the command line.
Generating Event Classes3:55
And further, here's a really cool thing. Yes, you can create your events and your listeners one at a time from the command line. So if we take a look, you'll see that yes, we can make an event, and yes, we can make a listener. But that can get a little tedious, at least in my mind. So instead, if you want, you can use the php artisan event:generate command. And basically what that does is it reads this here, and it figures out, do we need to create the respective files? So take a look. Right now, we have no events.
So take a look. Right now, we have no events. We just have the abstract class here. But no event files and no listeners. Now, if we run php artisan event:generate, it's going to read that event service provider and automatically generate anything that needs to be, well, generated. So now we have our UserWasBanned class or DTO, if you want to call it that. And then you have your handler or the listener. This is the class that is responsible for handling that event.
And then you have your handler or the listener. This is the class that is responsible for handling that event. And take a look at how readable that is. Handle the condition that a User was banned. So for example, you might do something like this. When we fire an event that says a User was banned, we want to pass through maybe the User or a userId. It doesn't really matter. It's up to you. Let's add that here and just say we're passing through the user object itself.
Well, if enough people click that, well, that means this User is probably posting spam and we should disable them. So we can use our logic to determine should that event be fired. And when it is, we will make an announcement to our entire application. Anyone who's interested, this User just got banned, respond however you want to. This is a nice, isolated, very readable way to handle these sorts of things. So we've specified within our EventServiceProvider that right now when a User is banned or was banned, I always like to write my events in the past tense. So anyways, when a User was banned, right now we're just doing one thing.
I always like to write my events in the past tense. So anyways, when a User was banned, right now we're just doing one thing. But if you need to do something later, then you simply add a new class and that will be triggered automatically as well. Maybe something like, I don't know, maybe if we ban them, we want to make sure that we cancel their subscription or something like that. I'm not sure, but that's fine for the example. Okay, well, we've added a new one. And yes, once again, we could make a listener or we can just run that event generate command again,
And yes, once again, we could make a listener or we can just run that event:generate command again, and it will detect, well, we don't have that yet. So I'm going to build that up for you. And now that handle method will be called in addition to the handle method here. This is what I mean when I say it very nicely follows the single responsibility principle. And it allows our code to not get too muddy, where you have 50 or 100 different lines just handling some event that took place. And usually that's in your controller. And before long, you see how code just begins to rot, right?
Listener Dependency Injection7:17
And usually that's in your controller. And before long, you see how code just begins to rot, right? Okay, but let's go ahead and delete that and just stick with the one event listener. Now within here, Laravel will work very much like your controllers where you get automatic injection. So for example, maybe you want the mailer component, or maybe you want the file system. It doesn't really matter. We don't have real code here.
It doesn't really matter. We don't have real code here. Maybe we have that. Well, like you always do, just type in it. And then when Laravel instantiates this class, it'll figure out, oh, you want a file system object. I'll go ahead and pass that through to you. So in a situation such as this, maybe you've created some kind of ApplicationMailer that you use. Just type in it and Laravel will pass that through for you.
maybe you've created some kind of application mailer that you use. Just type in it and Laravel will pass that through for you. Then you could simply say this mailer and call whatever method you created on that: send, ban, notification. Or if you even want to do it here, mail, send, you know, you have so many different choices. It's up to you to handle this however you want. In our case, we'll just say notify, and we'll say event user name that they have been banned from the site. Just a little pseudocode to show that we are triggering this.
Firing Events in Code8:31
and we'll say event user name that they have been banned from the site. Just a little pseudocode to show that we are triggering this. All right, so if I boot up a server with php artisan serve, and then if we switch over to our routes.php file, why don't we say right here, we'll fire an event. Remember, normally you just fire the event at what point in your logic it's appropriate. In our case, we'll just do it right here since we don't have a real project. Now, how do we represent this? Well, if you come from the Laravel four days, you might know something like this. Event::fire($user was banned, and then you could pass through your data.
Well, if you come from the Laravel four days, you might know something like this. event fire, User was banned, and then you could pass through your data. Now, in fact, you can still do that if you want. But for me, rather than using strings, I really like using objects. So instead, we can new up a class, and then pass through anything it needs through the constructor. And then further, there is a helper function called event that we can use. I'll show you. If we click through, notice that it just delegates to event fire anyways. But it's easier, so let's use that.
If we click through, notice that it just delegates to event fire anyways. But it's easier, so let's use that. Event, new, and we have UserWasBanned. And let's go ahead and import that at the top. Okay, so if we ban a User, we need to pass through the User who was banned. And we don't have one, so we'll just say new App\User. It doesn't really matter. Okay, but do you see how this works? When you want to fire an event or make an announcement that something just took place, you reference your event function, your helper function,
When you want to fire an event or make an announcement that something just took place, you reference your event function, your helper function, and then you new up the event object that you created. Then you can pass through anything that it requires. Often, it'll just be an ID or something like that. It really just depends. Now, behind the scenes, Laravel will automatically take care of the process of dispatching that event. I'll show you. If we come back and give this a refresh, there we go.
I'll show you. If we come back and give this a refresh, there we go. We fired the event, and because we had a listener registered, this class was instantiated or resolved out of the container, and then a handle method on it was triggered. Now, that's the basic event system, but there's also some other really cool things that you can do with Laravel 5 and also 5.1. When you generate your events and listeners, you'll see some of these use statements up here. What are they for?
Broadcasting and Queuing Events11:25
but you want to hear that announcement, so to speak, from your client side, well, that can always be a little tricky, and sometimes things don't sync up or the naming isn't quite right. All of it can get a little tricky. But now, it's so easy. If we take a look back at User was banned, there is the ShouldBroadcast interface, and all you have to do is implement it. Implements ShouldBroadcast. And now, basically, what's going to happen behind the scenes is
Implements should broadcast. And now, basically, what's going to happen behind the scenes is Laravel's going to check to see, okay, does this implement the ShouldBroadcast interface? And if it does, then that means they want us to broadcast this event using whatever driver they've selected. You could use a Pusher driver. You could use Redis. It's very much like the session config or the queue config, where you can choose any driver that you want to use.
and then have that handled behind the scenes. At least for me, that's how I like to think of queues and workers. It gives us a way to take these tasks that very well might take a good bit of time to process and just send it in the background so that we can return to the user and make the site a lot more responsive, at least in terms of loading. So anyways, if you want to specify that any listener should be queued, well, once again, we follow the same convention. You just implement shouldQueue.
well, once again, we follow the same convention. You just implement shouldQueue. And then behind the scenes, once again, Laravel is going to figure out, OK, does this implement the shouldQueue contract? And if it does, that means the user wants to throw this into a queue rather than handling it all synchronously. So at this point, let's say I'm using Beanstalk as my queue provider. Well, that's all I have to do. Add this section right here, and everything else will be taken care of.
Well, that's all I have to do. Add this section right here, and everything else will be taken care of. And then further, only if you need to interact with the queue, for example, the task will be deleted automatically. But if you want to have a little more control over this, you can see that you can pull in this trait. So all you'd have to do is say use InteractsWithQueue, and you can immediately reference those methods. But only if you need to. Many times, just adding implements ShouldQueue is all you need to do.
OK, at what point does this get triggered? This kind of makes it cleaner. Further, you can call php artisan event:generate to automatically build up these classes on the fly. Next, when you create your events, if you want to broadcast them to your client side, all you have to do is add this section right here, and you're good to go. Next, when you do fire the event, it's a nice, clean syntax,
Next, when you do fire the event, it's a nice, clean syntax, Laravel will automatically dispatch it for you. Then, when you handle it, you can handle it however you want to. And once again, if you want to throw that into a queue, then all you have to do is add about 10 characters or so, and that will be taken care of automatically. You gotta love it.
