تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Introducing Jobs Concept0:00

It can be tough. Once you get to this stage in your learning, well, you start to discover a lot of new terms that can be a little confusing at first. So we've already reviewed this idea of an event, a simple DTO that describes some event that just occurred in your system. And going in line with that, you also learned about listeners. How do we listen for that event and then respond accordingly? Well, now I'm going to introduce a new concept, jobs. In Laravel 5.0, this folder was called commands, but it was changed just to make it a little more clear what you're supposed to add here or what it's recommended that you add here. Of course, you can do anything you want for your own projects. Think of a job as a basic instruction that you'd like to handle in the backgrounds. Not exactly, but sort of like an asynchronous task. Something that you do want to be handled.

Generating a Job Class0:43

projects. Think of a job as a basic instruction that you'd like to handle in the backgrounds. Not exactly, but sort of like an asynchronous task. Something that you do want to be handled and you want to give it a readable name for this operation, but you want to throw it into the background so that you can respond and provide feedback to the user as quickly as possible. Why don't we take a look at a class first? If I run php artisan, naturally we have a generator for that. make:job. So let's try this. php artisan make:job. And I don't know, this could be anything that is relevant to your system. Maybe for something like a ReportsController, you have maybe a complicated report that needs to be handled. So maybe something like compileReports. It doesn't matter. Anything relevant to your application. Now, when we run this, you'll see it show up within the jobs folder right here. The constructor would be any arguments that you need

It doesn't matter. Anything relevant to your application. Now, when we run this, you'll see it show up within the jobs folder right here. The constructor would be any arguments that you need to pass through. And then the handle method, well, you can have automatic resolution with that. So if you require any dependencies or things like that, you can type into them right here and Laravel will automatically resolve and pass them through to you, which is very cool. But now in this case, yes, we have a job, but it's still basically synchronous. So it's going to be executed as part of the main cycle. So it will be executed in the same process or in the same request. And in some situations, that's exactly what you want. But what about when we want it to be queued? I want to say, yes, I want to dispatch this command or this job, but I do want to send it into the background. How do we accomplish that? And that's where we can use some artisan options.

Making Jobs Queued2:18

be queued? I want to say, yes, I want to dispatch this command or this job, but I do want to send it into the background. How do we accomplish that? And that's where we can use some artisan options. And if I run php artisan help make:job, you'll see that we have one main option here, queued. That indicates that the job should be sent to the queue. And because Laravel has a nice unified queue system, well, you can use Amazon for that. You can use Beanstalk. You can use iron.io or anything else. So let's try it again. php artisan make:job CompileReports. And maybe this is something that we can queue. We run that. And now you'll see just one main difference here. You'll see that we implement an interface here. And here's the awesome thing. That's all you have to do here. By simply implementing this interface behind the scenes, Laravel will detect that and figure out, okay, we need to send this command through the queue system. So why don't we try

to do here. By simply implementing this interface behind the scenes, Laravel will detect that and figure out, okay, we need to send this command through the queue system. So why don't we try this out? Because I want to show you how this can hook into other things like your event system and stuff like that. Now, remember, the handle method, you have automatic resolution there. So if you need a dependency, then just type into it and Laravel will pass it through. Then you can execute the task, however is relevant to your system. We'll use a var_dump. Compiling the reports within the Job class. Okay, so let's just figure out how we can trigger this. You're going to trigger or dispatch these jobs from typically your controller. But it doesn't have to be. You can dispatch jobs from any class in your system. You just have to pull in a trait that Laravel provides. But anyways, let's visit our routes.php file. And maybe we'll set up a resource for reports. And we'll call

Dispatching Jobs from Controller4:01

from any class in your system. You just have to pull in a trait that Laravel provides. But anyways, let's visit our routes.php file. And maybe we'll set up a resource for reports. And we'll call it ReportsController. And then we will generate that. php artisan make:controller ReportsController. And just a plain controller is fine. And in fact, because we don't really need a resource, why don't we just say getReports and send that to an index method. Alright, ReportsController, have our index method. And now all I want to do here is dispatch the job. Now let's take a look at this. If I go into Http, and we look at the AbstractController, you'll see that we pull in this trait DispatchesJobs. This is what you're going to use when you want to dispatch a job or command, however you want to call it. And you'll see mostly these are the same thing. The only difference is how you pass in the parameters or the data that should be associated.

dispatch a job or command, however you want to call it. And you'll see mostly these are the same thing. The only difference is how you pass in the parameters or the data that should be associated with it. So for example, if you want to new up a job class and dispatch it using Laravel's command bus, well, you can say this dispatch, and then you create a new instance of your job class, like this, this dispatch job. And let's create that job equals a new CompileReports. And we will import that at the top. Now, if CompileReports has any dependencies, you could pass them through right here. But that's not relevant in this case. So we new up our job class, and then we dispatch it. Behind the scenes, Laravel has its nice little command bus, where it will correctly dispatch it to your job, and it will then trigger a handle method on that object. Why don't we boot up a server and see if this works. And just to provide some feedback,

where it will correctly dispatch it to your job, and it will then trigger a handle method on that object. Why don't we boot up a server and see if this works. And just to provide some feedback, we'll say return done. Okay, so php artisan serve. And if I switch to Chrome and visit that URI, sure enough, we can see that the handle method on our job class was in fact triggered. And remember, because we are working locally, well, yes, this job should be queued. And in production, it would be sent through something like Beanstalk. But because we are working locally, that will be a synchronous task. So everything would still take effect within the same request, but only locally, not for production. Now, like I said, what about the situations where your job compileReports in this case, needs some kind of dependency that would be passed in from your controller in this case, maybe it's as simple as the ID of the report. Okay, well, let's save that.

compile reports in this case, needs some kind of dependency that would be passed in from your controller in this case, maybe it's as simple as the ID of the report. Okay, well, let's save that. And I'll show you how Laravel can very quickly take care of this. So let's go ahead and assign it. And well, I'm going to show you two ways to handle this. Down here, it says compiling the report with the ID, this reportId. Okay, just a little feedback there. Now, if we go back to our ReportsController, well, yeah, you could pass that through here. And if we switch back to Chrome, there you go, that was passed through. Or if this was coming from a request, which would be pretty common, maybe it's part of the URI, or maybe it's part of a form field or something like that. Well, you could just fetch that. And then we could say request and put reportId. Okay, now we'll simulate that just through the query string. And that still works. But as you can

Auto-Binding Request Data7:30

Well, you could just fetch that. And then we could say request and put reportId. Okay, now we'll simulate that just through the query string. And that still works. But as you can imagine, there might be situations where you really need to pass through a lot of request data through to your job. So on these situations, that would be kind of painful to build up this big constructor here. It's an option, but maybe we could clean it up. Let's go back to our parent controller class and then into dispatchesJobs. You've already learned about this one. Well, we have dispatchFromArray and then also dispatchFrom. Let me show you how this one works. If we go back, well, rather than doing up the job class itself, we could do this, app\Jobs\CompileReports, and then we could send through the request as part of it. Now, here's the cool thing. Behind the scenes, Laravel will automatically inspect the CompileReports

app Jobs, compile reports, and then we could send through the request as part of it. Now, here's the cool thing. Behind the scenes, Laravel will automatically inspect the CompileReports class. And it'll see, okay, you want me to pass through a reportId. And it'll then look into the request using that request object that we gave it. And it'll check to see, okay, is there a reportId field here? If there is, that's the value that I'm going to pass through here. And as you might have guessed, like a lot of other areas, the framework is using reflection here to figure out what should be passed through. So let's see that in action. Before we had dispatch to pass in an existing object, but now we'll use dispatchFrom. And if we switch back to Chrome, give that a refresh, you still get the exact same thing, but now you're not having to manually pass through all of that request data. Laravel will do it automatically. As an example, let's say that we

refresh, you still get the exact same thing, but now you're not having to manually pass through all of that request data. Laravel will do it automatically. As an example, let's say that we also need some other parameter here, maybe the type of the report or something like that. Okay, let's assign all of this. And now that's all you have to do. You don't have to return to your controller and change anything because we're using this syntax. So let's say the type and type equals we want a annual report. And well, we didn't see anything here, but trust me, it still works. Let's provide a quick bit of feedback, compile the I wish I use double quotes here, but that's okay. Come back, give that a refresh. And there you go. We are passing through those fields dynamically, which is pretty cool. And a quick note on this, actually, if I go back to ReportsController, if you don't want to use the syntax, and you are on

We are passing through those fields dynamically, which is pretty cool. And a quick note on this, actually, if I go back to ReportsController, if you don't want to use the syntax, and you are on PHP 5.5 or higher, well, you could always do this, you could import your class up here. And then you can use the class syntax. And that'll give you the exact same end results. But one small bonus to this is, well, it's a lot more friendly to your IDs. So if I want to click through this directly here is a lot easier versus using a string where IDs don't really know if they should inspect that or not. So anyways, that will give us the same end results. And you know what, why don't we rewrite this because it's driving me crazy. Why don't we use sprintf compiling the type Report with the id within the Job class. Okay, this type and this reportId. Alright, so what else do we want to review? Well, one thing that confused me when I was first learning about commands and events

Jobs vs Events Benefits10:55

with the ID within the Job class. Okay, this type and this report ID. Alright, so what else do we want to review? Well, one thing that confused me when I was first learning about commands and events is well, how did they differentiate from one another? What's the difference between dispatching a Job from your controller and firing an event somewhere in your system? And what you'll find is with most sizable projects, you end up with a situation where you want to make some kind of announcement that an event took place. And then that way, in a totally different part of your application, you can listen for that announcement, and then respond accordingly. Whether you are updating reports in a database like we're doing here, or you're firing off some email, or you're deactivating a User or any of that stuff. That's a great use for events. But you'll also have these sorts of jobs that are almost like first party jobs. They're crucial. They're things

your controller, well, maybe that's fine for a while. But what happens when there's this other instance, maybe through the command line or something else where you kind of want to do the exact same thing? And that's where you find yourself Googling, well, how do I call this controller from that controller? You've probably seen this on Stack Overflow all the time. Whenever you find yourself wanting to do that, it means you're missing some kind of abstraction. So if we create our jobs in this way, well, you can trigger this anywhere in your system. It's not locked to your controller or to your artisan commands. That's the second benefit. The third benefit is, well, for some of these jobs, they'll have a bunch of their own dependencies. So if you've ever fallen into that trap where you realize that over time, your controller just gets more and more dependencies, and then suddenly you realize, oh my gosh, there's nine dependencies on this controller.

into that trap where you realize that over time, your controller just gets more and more dependencies, and then suddenly you realize, oh my gosh, there's nine dependencies on this controller. Well, once again, that's because you started to miss something. You received these requirements, and maybe they keep coming in over the course of a year or two. And then each one requires another dependency. So you inject that, and that, and that. Well, that breaks down pretty quick. If you get over about five dependencies in your controller, or really any class, well, that might be a hint. Not 100%, but that might be a hint that you need to extract some things. So once again, a Job class like this is perfect for that. If you have this important task that has all of its own dependencies, then extract that from your controller, place it within a new Job class, and then you can automatically inject those dependencies into your handle method. And then finally, the benefit to

then extract that from your controller, place it within a new Job class, and then you can automatically inject those dependencies into your handle method. And then finally, the benefit to this approach is, well, we have these interfaces like we talked about. If you want this to be synchronous, then this is great. Or if we should throw it into a queue to handle it in the background, well, implement ShouldQueue, and you're done. So it's very user-friendly from that respect. And then finally, don't forget, it's perfectly appropriate for your Job class to trigger another task or another job. Or you could even fire your own event from here. So we could say event(new ReportWasCompiled). Now here's the thing. You don't have to think of this all up front. So it's not like you have to create an event for every single task that occurs. But if you fall into that trap where you think, well, I wish I could know when this thing over

So it's not like you have to create an event for every single task that occurs. But if you fall into that trap where you think, well, I wish I could know when this thing over here happens so that I can respond, then you have your hook where you think, okay, well, I'm going to go back to that class and fire an event from it, and then I can listen for it here. In this case, a Report was compiled. I'm not sure we need an event for that, but who knows? Maybe you do for what you're building. Now back to that idea of triggering a job from a job. How would that work? Well, if you think about it, it's almost circular in that way. You have a request, you dispatch a command, or you dispatch a job. Within that job, you handle it. But then from there, maybe you need to dispatch something else dependent upon some kind of outcome. There are situations when this would make sense. So while we don't really have a dispatch method

there, maybe you need to dispatch something else dependent upon some kind of outcome. There are situations when this would make sense. So while we don't really have a dispatch method here, so how do we handle that? I'll show you. Let's go back to controller, and you see how we have dispatches jobs here? You can import that anywhere you want. So if we were to come back here and at the top, import that, and use it, dispatches jobs. Okay, done. Now you can dispatch something else. So you have some kind of condition. If this turns out to be the case, then we need to respond in that way. So we will dispatch and new up some kind of different job. Let's handle that. php artisan make:job do something else, whatever is appropriate, and then do something else and import that. All right, we've now dispatched one job from another job class. And within here, we could just var_dump. Now, we are doing a different job. And remember, in this case,

import that. All right, we've now dispatched one job from another job class. And within here, we could just var_dump. Now, we are doing a different job. And remember, in this case, we did not add that queued flag. So this would be a synchronous operation. But nonetheless, if we go back to Chrome, we should now see two var_dumps, and we do. All right, so that's been your intro to this stuff. But really, there's quite a bit more to talk about. So we will continue touching upon this in the next couple of videos.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟