PATCH vs PUT concepts0:00
The update method handles two types of requests. The first is the patch request, which is what we typically think of for updating something. We would fetch a ticket, then update maybe the title, or the description, maybe both. Doesn't matter. The idea is that we're just updating a ticket with whatever information that we have. And then there is the put request, which is a replacement, basically. We fetch a ticket, then we replace all of the data in all of the columns for that ticket. And that's it. We are replacing something. So I tend to think of these as two completely different things.
We are replacing something. So I tend to think of these as two completely different things. Because yes, they can be both classified as updating, but really we have an update, and then we have a replace. And so I like to break this up into two separate methods, update and replace. And we would have a ReplaceTicketRequest, so that we could replace the ticket ID. And of course, we want the ticket ID here so that we can control the response. So that if the ticket doesn't exist, Laravel isn't going to use its default 404. We get to supply that 404. And of course, there are different ways of doing that.
Plan separate replace method1:17
We get to supply that 404. And of course, there are different ways of doing that. But this is just the most straightforward thing. It's right here in the code. We know exactly what's going on, and there's a lot to be said about that. So what I want to do in this episode is change this, so that our replace method is going to handle the PUT request. And we will implement the replace method both here on the TicketController and the Author'sTicketController. So let's start with this ReplaceTicketRequest.
Create ReplaceTicketRequest1:46
TicketController. So let's start with this ReplaceTicketRequest. And really, the easiest thing that we can do is take our StoreTicketRequest. Let's copy that, rename the copy to ReplaceTicketRequest. And the idea here is that replacing something is very much like creating something. Except that we have to have a Ticket already in the database. But everything else is going to be the same except for our rules here. Because in the case of a replacement, we need to be sure that we have all of these attributes because we are going to be replacing all of these attributes with whatever was supplied in the request.
attributes because we are going to be replacing all of these attributes with whatever was supplied in the request. So here, we want to be sure that we have a title, description, status, and the authorId. If we wanted to be real sticklers about this, we could also say that we also need the date fields, the createdAt and modifiedAt. But I think this is going to be fine for us there. We also get the benefit of having this messages method already given to us so that we can use our custom error message for invalid statuses. So as far as that is concerned, yeah, we are good to go.
Group routes and setup PUT2:52
use our custom error message for invalid statuses. So as far as that is concerned, yeah, we are good to go. So let's go back to our TicketController. Let's add a use statement here. But then we need to set up the routes. So let's go to our api/v1 file. And we're going to clean this up a little bit because for one thing, notice that every one of these lines of code starts with route middleware auth sanctum. And we are going to be adding in more entries here because whenever we set up the routes for our ticketsController, we are going to chain the except method so that we can set
And we are going to be adding in more entries here because whenever we set up the routes for our TicketsController, we are going to chain the except method so that we can set up the routes except for the update route. So that then we can come in and say that for a PUT request, we want tickets/ticket. And that is going to be on our TicketsController and the replace method. And whenever we add the routes for the PATCH requests, and then we do the same thing for the author's ticket, it's just going to get messy. So let's do this. Let's go ahead and let's group these together so that we'll go ahead and call middleware and we'll use the auth:sanctum middleware.
Let's go ahead and let's group these together so that we'll go ahead and call middleware and we'll use the auth:sanctum middleware. But then we will group all of these together so that we can take all of these routes and we can get rid of what we call the middleware method. And that's going to make this a lot cleaner. So with this in place, we will be able to go to Postman and set up our requests for our PUT request. So just like our Request class, let's duplicate our Post here because this already has a body set up and we will need a body for our PUT request. So let's change the name to putTicket and we'll change the type to a PUT request.
set up and we will need a body for our PUT request. So let's change the name to putTicket and we'll change the type to a PUT request. We do need a specific ticket here. So let's just use, well, no, let's create a new one. But I guess first we need to make sure that this is going to work, don't we? So let's go to our TicketController and let's just return replace so that we can send this request. We should get replace. Great. We do.
Implement replace in controller5:03
Great. We do. So we are good to go there. So now let's implement this. So the first thing that we want to do, well, really, since replacing is a lot like creating, we can take the code for our store method. Let's just copy everything here. And we'll use that as a basis for our replace method so that the first thing that we will need to do is try to find the ticket with this ID. We don't need the User here.
need to do is try to find the ticket with this ID. We don't need the User here. So we will have our ticket, we'll call findOrFail, and then pass in that ticket ID. Now in case the ticket doesn't exist, we need a different message here. So let's just grab this line from the show method so that if the ticket doesn't exist, we say that the ticket cannot be found. Otherwise, we are going to create this model and we won't actually create the model. What we'll do is we will update the ticket. So we will call tickets update. We will pass in the model that will update all of the columns because we have all of
So we will call tickets update. We will pass in the model that will update all of the columns because we have all of the columns. Our request class is going to make sure that, and we don't want to create that. We just want to return a new TicketResource with the provided ticket. So that should, yeah, I think that will work just fine. So let's test this out. Let's go back to Postman. And let's first of all create a new ticket. So let's call this replace this title.
And let's first of all create a new Ticket. So let's call this replace this title. Then for the description, we will have replace this description. For the status, we'll set that as A for active. For the authorId, let's just use the authorId of 1. So this should create a new Ticket. We should get the response. We do. We have an id of 101. And so now we can go to our PUT request.
We have an ID of 101. And so now we can go to our put request. Our ID is going to be 101. And then we just need to make some modifications here. So for our title, we want to change that. We can say changedTitle. The description can say changedDescription. Let's change the status. We're just gonna change everything here. We'll change the status to completed.
We're just gonna change everything here. We'll change the status to completed. But I'll tell you what, let's take out the author_id. And let's try to send this request. We should get a validation error. So hopefully we do, yes, that the author_id is not provided. So let's add that back. We will send that request. It should update. So there we have our ticket.
It should update. So there we have our ticket. We have our attributes, titles, status. The description is missing. Why is that? The authorId, did we change the authorId? Yep, we did. We changed that to 2. Okay, so that worked. I'll tell you what, let's get that ticket
Fix TicketResource description7:53
Okay, so that worked. I'll tell you what, let's get that ticket that was ID of 101. Let's look at the description. We get the description and that was at least changed. So why don't we get the description here? Oh, yes. Inside of our TicketResource, we have this right here. We are only showing the description when the route is tickets.show.
We are only showing the description when the route is tickets.show. And that's not gonna work because we need to be able to show it, not just for the show, but for the replace route that we just created. So we're gonna need to change this. In fact, let's reverse this. Let's say that we want to include the description if the route is not, and then we will have our list.
Let's say that we want to include the description if the route is not, and then we will have our list. So we primarily didn't want to show it for the tickets index, but we also don't want to show it for the author's tickets index. That is for whenever we make a request to get a particular user or a particular author and get their tickets. So we don't want to show the description there.
and get their tickets. So we don't want to show the description there because that's essentially the same thing as the index of our tickets, except that now this is scoped to the authors. So we don't want the description for the ticket index. We don't want it for the author's ticket index. And I guess we don't want to show it here for whenever we get our authors and we include the tickets.
for whenever we get our authors and we include the tickets. So let's see if we get the description. I'm pretty sure we will get the descriptions there. Oh, no, we won't. Okay, so let's leave that as is. If the route is not the tickets.index or the authors.tickets.index, then we will include the description. Okay, so with that in place,
then we will include the description. Okay, so with that in place, let's go back to our put and let's make some more modifications here. So we'll say changedTitleTwo, changedDescriptionTwo. Let's say that the status is going to be canceled now. We'll leave the authorId alone. So we will send that. We should get a response that includes the description. Perfect.
Add replace to AuthorTicketsController10:12
We should get a response that includes the description. Perfect. All right, so now we just need to implement the same functionality, but for our AuthorTicketsController. So let's close some of these files. I don't think we need anything in the TicketResource anymore. So let's close that. Let's copy our replace method here.
So let's close that. Let's copy our replace method here. We're just going to straight up copy and paste that into our AuthorTicketsController. And let's change the parameters. So of course we need a use statement for our ReplaceTicketRequest. Then we will have the authorId. Then we will have the ticketId. So we essentially want to do the same thing.
Then we will have the ticket ID. So we essentially want to do the same thing to where we fetch the ticket, but then we want to make sure that the ticket belongs to that User. So we did that inside of the destroy method to where we checked if the ticket belonged to the User. Now, you know, one option, it's not really an option because we are doing this so that we can control the response,
it's not really an option because we are doing this so that we can control the response, but it would be nice if we could use a scoped thing here for our nested Controller so that we could say that our Ticket is scoped to the Authors. But you know, this is fine. This is fine. Okay, so let's go back to our AuthorTicketsController and we don't want to delete. We don't want our message saying
and we don't want to delete. We don't want our message saying that anything was successful. We just want to check if the ticketUserId is the authorId, then we will do the same thing. We will build this model array so that we can update the ticket and then we will return that ticket response. Although, you know, we should do something in case if this fails.
Although, you know, we should do something in case if this fails. I just don't know what I want to do yet. So let's just add a TODO. Ticket doesn't belong to User. Okay. So with that in place, we should be able to come to our users collection. Let's duplicate our POST request here so that we will have our PUT User Ticket.
Let's duplicate our post request here so that we will have our put user ticket. Let's change the request to a put request. And here, let's say we will get user. Let's just get the userId of one and the ticket is going to be an ID of 20. So for our put user ticket, author/1/tickets/20. So we have the body here. Let's change this.
So we have the body here. Let's change this. What do we have? Okay, we have some Latin here. So for the title, we'll say PUT request works. The description is implement replace method. The status, let's complete it. And we don't have the User, but let's just test it once again. Method update does not exist.
but let's just test it once again. update does not exist. That is because we need to set up the route here, don't we? So this is for our nested resource. And we essentially want to do the same thing to where we chain the accept method because we want all of the routes except the update route. And then we want a PUT request. So here we will have authors/ and then the author and then tickets/ ticket.
So here we will have authors slash and then the author and then tickets slash ticket. The controller is our AuthorTicketsController and the method is replace. So that should take care of that. We send this, we should get a validation error. We do. So now we just need to add the relationships and then the author and then the data. And we have the id of one.
and then the author and then the data. And we have the ID of one. We'll just keep the author the same. So we will send that. We get the response back of our updated ticket information and we're good to go. So we have successfully implemented the PUT request for both our tickets and our AuthorTicketController. So in the next episode, we will implement the update method.
So in the next episode, we will implement the update method.
