Spotting Duplicate Forms0:00
Let's take a look at a common refactor we can do to dry up our code between create and edit forms. So I have a simple blog implementation here. We can list our posts. We can view our posts. We can edit our posts. Let's update this and this as well. And we can create our posts as well. So say newPost, newPost here. There's no authorization here as this is just a simple demo, but oftentimes you'll
So say new Post, new Post here. There's no authorization here as this is just a simple demo, but oftentimes you'll find that the form for creating the Post and updating the Post are almost the same. So if we go to edit a Post, you'll see that this form and the create Post form are almost the same. And a lot of times you might find that you just duplicate the code, which is what we have here. So if you take a look at the create form and the edit form down here, you'll see that they're almost the same with a few differences. So one difference is the endpoint.
almost the same with a few differences. So one difference is the endpoint. So this is the endpoint for updating the Post. And for create, we have the endpoint for creating a Post. Also for our value here, you can see for creating a Post, we just have the old value here. But for updating a Post, we also have the default value here as a second param to the old method. And I think the only other difference is the name of the button here. So updatePost and createPost down here. And everything else is pretty much the same.
Extracting Blade Component1:18
So update Post and create Post down here. And everything else is pretty much the same. So let's see if we can dry up our code here. So let's start with the edit form. I'm going to extract the form to a Blade component. So the form, let's grab this. Let's cut that out. Let's name it PostForm. So . And we have to pass in the post here.
So XPostForm. And we have to pass in the $post here. So we can say $post equals $post. Okay. And let's make a new anonymous component here. But within the components folder, we can say post-form.blade.php. We can paste in our code. Let's go ahead and save these files. And editing should be the same if I did that correctly. So let's try that out.
And editing should be the same if I did that correctly. So let's try that out. Let's edit this one here. Edit, changed, changed. And let's hit update post. Okay. So that still works. And let's see if we can do something similar for creating a post. So let's go to the create.blade.php. Let's comment out the form for now.
So let's go to the create Blade. Let's comment out the form for now. And we'll use that Blade component as well. So it's XPostForm. But it is expecting a Post to be passed through, but we don't have one when we're creating a new Post. Let me just add that code for now. Because we are going to pass an in-memory instance of a new Post. So let's go to the endpoint where we're showing this form. Usually this would be in a controller, but for this series, I'm just putting everything
Passing New Model Instance2:43
So let's go to the endpoint where we're showing this form. Usually this would be in a controller, but for this series, I'm just putting everything in our routes file. So let's go to that. It should be up here somewhere. So right here, this is the endpoint that shows the create form. And right now it won't work because it's expecting a post. So right here, and it should be null. See if we get that error. Okay, undefined variable post.
See if we get that error. Okay, undefined variable post. So we can just new up an instance of post and pass that through. Let's go back to here. Let's say our post is just new post. And like I said, this will just be an in-memory instance. So when it gets here, or in the Blade component, so post form, whenever we use it here, the field will just be null. So now our create form should show. So let's refresh this, and it does show.
Conditional Create vs Update3:33
So now our create form should show. So let's refresh this, and it does show. So now we have to make sure it points to the correct endpoint, whether we're creating or updating a Post. So right now we're just using the endpoint to update the Post. So we need a conditional to check which case we want to handle. So let me just move this method up here. So this is the case when we're updating a Post, and we can check if the post actually exists in the database. And if it does, we'll use this endpoint.
exists in the database. And if it does, we'll use this endpoint. And if it doesn't, then we'll use the create endpoint. So let's say if, make an if else block here, we can use the exists field on the model. So post exists. So this will check if it actually exists in the database. And in this case, we want to update the post. So we can grab all of this and put it in here. And let's delete this actually. But if it doesn't exist, then use the create endpoint.
And let's delete this actually. But if it doesn't exist, then use the create endpoint. So let's grab that from here. So it's just this right here. So let me just grab this. Let's paste that in here. Let's remove the comment. And let's go ahead and save that. Okay. And I believe we also need this down here, where we're showing either create or update.
Okay. And I believe we also need this down here, where we're showing either create or update Post in the button here. So let me just reformat this. And we can do pretty much the same thing here. So if $post exists, then update Post. But if not, the text should be create Post. Okay, let's try that out. Let's save this again. Let's go back to the browser.
Let's save this again. Let's go back to the browser. Let's refresh this. So it is createPost here. Let's see if it actually creates a post. Testing, testing, create. And it does. Cool. Let's make sure update still works. Let's go ahead and edit this post.
Let's make sure update still works. Let's go ahead and edit this Post. Changed, changed. And let's update the Post. You can see the text is correct. And the update does work. Let's make sure the error messages still show. So let me just remove this and hit update. And it does. Cool.
Refactoring Shared Fields Logic5:36
And it does. Cool. Let's make sure it still works for creating as well. And it does. So we still have some duplication when we're updating or creating the Post here. So when we're creating it, we have post create and we're passing through the fields here. And I'm just hard coding one here because I don't have any authentication in place. But in reality, this would be $authID. So the logged in user's ID. And we also have something similar when we're updating the Post.
So the logged in user's ID. And we also have something similar when we're updating the Post. So down here, you can see this is sort of duplicated. So one approach would be to extract this to a method. So let's do that first. We would grab the fields here. Let's make a method here called fields. And we'll pass through the $request. And let's go ahead and make that method down here. And again, ideally, this would be in a controller, but this should be fine for our demo here.
And let's go ahead and make that method down here. And again, ideally, this would be in a controller, but this should be fine for our demo here. So let's say function fields takes in a $request. And we can just return that array of fields. So let's return this, make sure to add our semicolon here. And let's use it for the other method as well. So let's grab this. And let's use it for creating as well. So up here, we can get rid of this and use that new method. So again, the benefit of this is we only have to change things in one spot.
So up here, we can get rid of this and use that new method. So again, the benefit of this is we only have to change things in one spot. So let's see if this works. Let's refresh this new title. And let's create that post does work, make sure updating works as well. And it does. Cool. Now another way would be to push this logic into the form request here. So I do have this PostFormRequest, which handles the validation. So you can see we have our validation rules here.
So I do have this PostFormRequest, which handles the validation. So you can see we have our validation rules here. But how about we add another method here, which is responsible for updating or creating the Post. So let's make a new method. Let's call it updateOrCreate. And this is going to take in a Post, make sure to import Post here. And we're going to do almost the same thing here. So in our helper method down here, but we have to call the save method. So we have to update each field, so post, start with the userId.
So in our helper method down here, but we have to call the save method. So we have to update each field, so post, start with the userId. And again, we're just hard coding it to one in this demo, we have the title. And since this is a request, we can just say this->title. And same for our body. So post body is this->body, and we have to make sure to call the save method here. So it works for both creating and updating the post, so we can say post->save(). So now back to our routes file, instead of doing it this way, we can just call that method we created on the request. So we don't need this anymore.
we created on the request. So we don't need this anymore. We can say request, update or create. And we want to pass in the post here, which is coming in from route model binding. And we can do the same for creating as well. So up here, we can comment this out. And we can use that same method. But we are not getting the post here. But we can do the same thing and just pass in a new instance, a new Post. So again, in this case, we have a new Post, we are updating the fields here.
But we can do the same thing and just pass in a new instance, a new Post. So again, in this case, we have a new Post, we are updating the fields here. And then we are calling save to persist it to the database. So let's give that a try. Let me refresh this. Let's try updating. Let's just get rid of this. And this as well. Let's update. Okay.
Let's update. Okay. And let's make sure create works as well. create works. And it does. Cool. So yeah, pretty simple refactor. Again, the benefit of this is if you have to add a new field in the future, you only have to update it in one place. So let's go ahead and try that out.
Adding Excerpt Field9:25
have to update it in one place. So let's go ahead and try that out. Let's make a new field on the Post. Let's call it excerpt. So like a preview of the body. So let's go ahead and make a new migration. So php artisan make:migration, let's say update posts table, add excerpt field. And the table is posts. Let's add that field in our database. So update posts table, let's just make it a string here.
Let's add that field in our database. So update posts table, let's just make it a string here. So let's say table, string, excerpt. And let's put it after the body column. So after body, and let's make it nullable. Okay. So let's go ahead and migrate that php artisan migrate. So we should now have an excerpt field in our database. Let's refresh this. There it is.
Let's refresh this. There it is. It's null by default. So let's actually show that excerpt field in our index.blade.php. So with an index.blade.php, let's wrap this in another container div. So say empty for, and this is the title, and this will be the excerpt. So let's say div, let's just say post excerpt. And they're all null now. But let's see what's first and we'll manually add one and then we'll update our form. So back here, create should be first.
But let's see what's first and we'll manually add one and then we'll update our form. So back here, create should be first. So let's manually add one first. So this one, this is a preview. Okay. Let's go back here. Okay. So it does show. And now we should easily be able to add this field in our forms because it only appears in one place.
And now we should easily be able to add this field in our forms because it only appears in one place. So let's go to our Blade component, PostForm. We can add the field here. So let me just grab the field for our title and put it underneath the body here for our excerpt. Let's just grab all of these, let's say excerpt. Okay. So let's save that. Now within our PostFormRequest, so PostFormRequest, we can update both our validation.
So let's save that. Now within our PostFormRequest, we can update both our validation rules and our actual fields. So let's say excerpt here. This is fine. And we can add a new one down here as well. So let's update this. And if I did everything correctly, this should now appear in our forms. So let's go to this one here. Let's update the Post.
So let's go to this one here. Let's update the post. There's the excerpt. Let's say hello there. Let's update that. Let's see if that shows. There it is. And let's see if it works on new posts as well. So new post, hello again, excerpt here. And there it is.
So new post, hello again, excerpt here. And there it is. So yeah, definitely keep this refactor in mind whenever you have a lot of duplicate code between your create and edit forms. So let's go ahead and make a commit here. This is episode eight. Let's call it share code between create and edit forms.
