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

Messy Controller Problem0:00

(upbeat music) Did you know that Laravel forces you into bad architecture? Well, it does. Not really. So we have our post controller. We've seen this before, except now I've added a store method so that we can publish a post. And what do we do? We validate, we get the user, we check if the user is an author. We also check if the user has published a post

We validate, we get the user, we check if the user is an author. We also check if the user has published a post with that given title. Because if they have, then well, they can't publish that post. And then we create the post, we writes to the log and then we redirect. So what was that I wasn't counting, but was that like five different things all in one place? Probably so. So let's refactor this.

Extracting Validation0:47

Probably so. So let's refactor this. And really the best place to start is with the validation. So Laravel, of course, has tools available for us to validate incoming input, incoming input. I'll run with it. So we'll use artisan to make a request called publish host request. And the first problem with this particular approach is that if you type an artisan incorrectly,

And the first problem with this particular approach is that if you type an artisan incorrectly, it doesn't work at all. So this is going to give us that publish post request and the great thing about this is now we can extract that validation into another class and it can be done automatically so that it doesn't even really appear inside of our controller. So we'll type in this publish post request for the method parameter here.

So we'll type in this publish post request for the method parameter here. And we'll just need to take this out and put it inside of the publish post request class. Authorize, we need to change to true, so that we can actually perform this request. And all I'm going to do is take the validation rules, put them inside of the return array, and that's it. And you know, it's a form request. It's not extra architecture.

And you know, it's a form request. It's not extra architecture. It's part of Laravel. It is one of the best things about Laravel so that we can extract the validation, which gives us so many other benefits because now not only is it not in the controller but we have this dedicated area for validation which means that we can test this if we wanted to. So we could write a test that focused specifically

which means that we can test this if we wanted to. So we could write a test that focused specifically on validating our form input and there we go. We couldn't do that before, but now there it is and it's automated so we don't have to worry about actually performing the validation. But then what do we have? You know, we have a lot of business stuff here to where this is still kind of validation but not really. But then we also create the post.

Introducing Publish Action2:49

to where this is still kind of validation but not really. But then we also create the post. And you know, there's many different ways that we could extract this. But I kind of think of this whole thing here as a single action because what is the action? The action is to publish a post. But in order to publish a post, we have to go through all of these other rules here. So I think what we could do is create a class

we have to go through all of these other rules here. So I think what we could do is create a class that represents the action of publishing a post. This is a common approach. It might not be called an action, it might be called a command. I mean, there's a lot of different words that people use but ultimately I like to think of it as the command pattern so that we have a command that we execute. In order to have a command or an action, we need to make the class

In order to have a command or an action, we need to make the class and we'll just call it publish post because that is what this action is for. So if we open up publish post, you know, we don't necessarily need anything for the constructor in this particular case because we want to be able to create this published post and then execute this regardless of anything. We want it to be reliant upon the information

and then execute this regardless of anything. We want it to be reliant upon the information that we pass to whatever method that we're gonna use to actually execute the action. Some people will call it execute. Some people will call it handle. There's a lot and Vogue is one of those. There is no hard and fast rules. You can use whatever you want. I typically reach for handle just because that's me.

You can use whatever you want. I typically reach for handle just because that's me. And what do we need to do in order to publish a post? So we need to get the user. We need to check if they are an author and all of that stuff. So we need, first of all, the user that is going to be publishing this post and then we need the data. The data is used to, you know,

and then we need the data. The data is used to, you know, check if the title already exists for that user and of course to create the post. So we'll just say that we'll get the user. We'll also get an array that contains the data but then we need a return and what do we do? So if it's already used, you know, this is response specific but an action typically isn't.

Designing Action Return5:04

this is response specific but an action typically isn't. An action is something that we can, if we design it correctly, it could be isolated. So two, we could test it or we could use it in other parts of the application so that if we needed to say publish a post from a queue or something like that, we should be able to do that. So ideally we won't have any kind of request or response things from this action.

So ideally we won't have any kind of request or response things from this action. So I think since we are publishing a post, it should probably just return a post. And before we get any farther, let's add the use statements for those models. And then, I mean, it's just a matter of lifting the code out of our controller and then pasting it inside of that class. And we can also say that the log would be part of that as well because, you know, when you think in terms of publishing a post,

And we can also say that the log would be part of that as well because, you know, when you think in terms of publishing a post, the action of publishing a post, the log is included there. So let's include the log facade. We need to address our return here because that was very specific for the response. But again, we want this to be agnostic. We don't want it to rely upon a request and response. So one thing that we could say is that, you know, this is kind of validation

So one thing that we could say is that, you know, this is kind of validation because we are checking if the user is an author, if the user has already used that title, then, yeah. So maybe we throw a new validation exception that's from the Illuminate. And we want to include the message and we'll just take this title. You already used the title and we will use that as one of the messages for the exception there.

You already used the title and we will use that as one of the messages for the exception there. And yeah, although this doesn't like unexpected name, is that really unexpected? I mean, IntelliSense popped up with that, didn't it? With messages, although what was the, I'm taking too much time on this. Okay, it says messages, accepts an array, okay? I'm gonna leave it and I'm gonna say that Visual Studio Code is wrong

I'm gonna leave it and I'm gonna say that Visual Studio Code is wrong because it can be wrong many times it is. So what do we want to do? We create our post, we log that and then we will return our post. So now our action is isolated, it's by itself. We can use this inside of our controller or we could use it from a queue or anything like that. So now it's just a matter of using that here

Using Action in Controller7:36

or we could use it from a queue or anything like that. So now it's just a matter of using that here inside of our store method. And why not just do this? We'll have our publish post and we could just call it action for the lack of a better term so that now we can write code that looks like this. We'll get our post and we will use our action to handle the action by passing in the user

We'll get our post and we will use our action to handle the action by passing in the user but then we also need the data from the request. So we will use the validated method to return the validated information so that then we redirect with the post ID and there we go. So we took that big huge fat controller method and now it's just a few lines of code. We extracted the validation so that it's isolated into its own thing

We extracted the validation so that it's isolated into its own thing so that we can reuse it and test it if we need to and then the act of publishing a post. We once again extracted that into its own thing so that now we could test that functionality or we could reuse it to another parts of the application so that we can publish a post from a queue or we could even create a console command to publish a post.

Lean Controllers Summary8:48

or we could even create a console command to publish a post. I mean, the sky's the limit. So yes, Laravel makes it easy to write messy controllers but really what framework doesn't? I mean, it doesn't force you into writing messy controllers. In fact, Laravel gives you the tools that you need in order to write clean and very lean controllers. I mean, form requests go a long way towards reducing the size of your controllers

I mean, form requests go a long way towards reducing the size of your controllers and of course, if you take the idea of an action, well then you're gonna make your controllers even smaller.

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