Add Comment Form 0:00In the last episode, we set up the logic to display any comments associated with a post. But we manually created those comments within SQL Pro. In this episode, however, let's set up a form so that we can do it right here. We're going to go to our Posts show view. This is where we display a post. But then how about right around here, we'll have a section to add a comment. So maybe we'll set up a card here. I think this is part of Twitter Bootstrap 4. Let's see. Yeah.Let's see. Yeah. Okay. So let's give it some space. And we'll have a section to leave a comment. So we're going to have a form here. And let's set up a form group. And then we'll have a text area here. So the name will be the body. And the placeholder will be your comment here.So the name will be the body. And the placeholder will be your comment here. All right. Let's also give it a class of form control. Okay. Refresh. It didn't look that great, but it's fine enough. Finally, we'll duplicate this and we're going to have one more section for our Submit button. And you know what? We can just steal this from our other form.And you know what? We can just steal this from our other form. So let's just grab that. And let's see. We'll say Add Comment. Okay. Refresh. And there you go. So now we're going to fill this out. And when we click Add Comment, well, once again, think back to the RESTful training Set Form Action 1:14So now we're going to fill this out. And when we click Add Comment, well, once again, think back to the RESTful training that we talked about. We are creating a comment. So our method will be Post. And by the way, if the method should ever be Patch or Delete, you can use the method field function. Now, why do we do this? We do it because right now at the time of this recording, most browsers don't understand anything but GET and POST.We do it because right now at the time of this recording, most browsers don't understand anything but GET and POST. So if you want to do a DELETE request or a PATCH request, it's just not going to work. So instead, we sort of fake it. We create a hidden input where we say our intended request type. And then our server will detect this and understand, oh, you actually meant for a PATCH request. So I will route it accordingly. Anyways, the action will be... and well, this kind of comes up to you. The action could be slash comments. That would be fine.The action could be slash comments. That would be fine. The action could also be the POST and then the POST ID slash comments. That would be fine as well. Generally, I would say don't go more than about two levels. Maybe sometimes you have to, but I promise you the more you nest, the more it'll get tricky and the more you're going to suffer a little bit having to work with those URIs. So in this case, I think one level deep is fine. That will be our action. So let's give it a shot. Create Comments Controller 2:30That will be our action. So let's give it a shot. Now we know it's going to fail because we don't have an endpoint set up for that, but we can see that it sent us to the correct place. So let's go to our route slash web file and we're going to say when we get a POST request to POST and then a POST and then comments, well now, do we do POST controller? But what would the method be for that? You could do something like store or add comment. A lot of people would do that. You also might find that this is an opportunity to create a whole new controller called commentsA lot of people would do that. You also might find that this is an opportunity to create a whole new controller called comments controller and what you'll find is sometimes when you don't create a weird method name but you instead extract a new controller, you can return to your common action names like this. So in our case, this would now be comments controller at store. Let's stick with that. phpArtisan, make me a controller called comments controller and that will now be in our HTTP controllers directory. So we have to add a store method.controllers directory. So we have to add a store method. So now this will receive the POST and I'll make sure that I import that at the top. But we also want to work with a comment. So let's pull that one in as well. So now I'm going to show you the long form method and then we'll talk a little more about clarity and ways we can improve this. But the long form way would be to say comment create and let's be explicit here. The body of the comment will be equal to whatever the user typed into that text area. Next, the POST ID will be equal to the ID of the POST. Add CSRF Protection 3:53The body of the comment will be equal to whatever the user typed into that text area. Next, the POST ID will be equal to the ID of the POST. So we could do that and then return a redirect back to the previous page or there's a helper function called back that we can use instead. All right, so let's just try this out. Let's go back, give it another shot. Here is my comment. Add it. Ah, but now we get a token mismatch exception and we talked about this, right? Any form will need to have a CSRF field to protect you.Ah, but now we get a token mismatch exception and we talked about this, right? Any form will need to have a CSRF field to protect you. So let's add that. All right, come back one more time. Here is my comment. It's been posted. We didn't provide much feedback, but we'll talk about flash messaging and things like that soon. But sure enough, we can see the comment there. So that's fine. Move Logic to Model 4:39But sure enough, we can see the comment there. So that's fine. It works great. But now here's some other things you might consider. What are we actually doing here? Well, you know, if you were talking to the client that you are working for, they would say something along the lines of, well, we need to have a section so that you can add a comment to a POST. But we're using comment create here. Well, we haven't necessarily represented that terminology, add a comment to a POST.But we're using comment create here. Well, we haven't necessarily represented that terminology, add a comment to a POST. So wouldn't it be nice if instead we had a method on POST because we're saying to a POST. So maybe POST can be responsible for this. And maybe we could just say POST add comment. Then the actual query doesn't matter. That can be hidden behind this method and you end up with something like this. Cool. So let's do this. Let's pass through the body of the comment.So let's do this. Let's pass through the body of the comment. And it sounds like we need to add a new method called add comment. Add comment. We accept the body of the comment. And now, again, we could say comment create here and do it the long form way. So we could say the body is equal to the body. And then the POST ID is equal to not POST because we're in an instance. So I could say this ID. And yeah, that would be an option as well.So I could say this ID. And yeah, that would be an option as well. So we come back. This looks pretty clean to me. We give it a refresh. Yet another comment. And this will work. Come down and there it is. But now I'm still not done. We're going to come back to POST and there's another way we can represent this.But now I'm still not done. We're going to come back to POST and there's another way we can represent this. Rather than manually specifying the POST ID, well, we already have a relationship here, right? Well, with Eloquent, we could do this. This comments and create a new one where the body is equal to what was passed in. Or as we learned, we could just do compact to do the same thing. So now we could do this. Let's give it another shot. One more try.Let's give it another shot. One more try. Add comment. And there you go. That works as well. So you'll see that Eloquent is really, really flexible when it comes to these relationships. In other words, if we were to say this comments, that would return to us a collection of all comments associated with the POST. On the other hand, if we say comments create, where we trigger it as a method, well now, yes, we give it the body, but behind the scenes, it will also set the ID of the POST on theOn the other hand, if we say comments create, where we trigger it as a method, well now, yes, we give it the body, but behind the scenes, it will also set the ID of the POST on the new comment. And it will do that for you because of the relationship we set up here. So now think about it. If we come back to our controller, this almost exactly matches the way our fictional client would speak about this. Hey, can you give us a new section so that we can add comments to a POST? Sure. We come to our code and we repeat that exact name, add comment. Validate and Show Errors 7:22Sure. We come to our code and we repeat that exact name, add comment. You can't get much more readable than that. So finally, to finish up, let's add a layer of validation. I'm going to validate the request and the body is required. And you know, you could even do things like, well, you have to give us at least a minimum of two characters for us to consider it as valid. So that's fine. But now what if validation fails, as we've discussed before? It redirects back.But now what if validation fails, as we've discussed before? It redirects back. It doesn't create the POST, but we're not displaying the errors. Well, if you remember a couple episodes ago, we set up a special partial. Let's go into Views, Layouts, and we have this Errors partial. So let's just reference that and see if it does the trick for us. Right down here, include Layouts.Errors. OK, one more time. Fail validation. It runs.Fail validation. It runs. And sure enough, we have our errors. I'm happy with this. So now I would just finish off by forcing you to type something in. So this will give us some browser-level validation. But if they circumvent that or use a browser where that's not supported, we'll next have some server-level validation. And I think we're all set to go here. Great job.And I think we're all set to go here. Great job.