Setting Up DELETE Request0:00
Deleting resources is probably the most straightforward thing that we can do, and it's probably the easiest thing that we will implement in our entire API, because all we need to do is delete our resource. We're done. See you next episode. No, I'm kidding. There is more that we need to do. Like, for example, let's head on over to Postman. Before we do anything, as far as our code is concerned, let's copy the PostTickets request. Let's make some changes.
Before we do anything, as far as our code is concerned, let's copy the PostTickets request. Let's make some changes. Of course, this is going to be DeleteTicket. We need to change the request type to Delete. Let's try to delete a ticket with an ID of 800, something that we know doesn't exist. Whenever we send that request, we are going to see, well, it's a 404, obviously, because the ticket doesn't exist, but look at all of the information that we get. In the previous episode, we talked about security through obscurity. We want to hide as much of our applications working as possible, and this isn't doing that.
Implementing Ticket Deletion1:04
We want to hide as much of our application's working as possible, and this isn't doing that. So we need to really control the response that we send. So instead of having a ticket as our parameter here, let's just have the ticket ID, so that we could do something like this. We could try to find that ticket, but we could use the findOrFail method, so that if it does fail, we can catch that exception, and we would be good to go there. So here we will simply delete the ticket if it exists, and then we want to return something back to the client that says, this was successful. So let's just return an OK, and ticket successfully deleted.
Handling Missing Tickets1:45
back to the client that says, this was successful. So let's just return an OK, and ticket successfully deleted. That's going to be just fine. Now if that ticket doesn't exist, we want to catch ModelNotFoundException, and then we need to discuss what do we return in this particular case, because in the previous episode, we talked about returning something other than a server error if we encountered a server error, because we want to hide as much as the implementation and as much of the application problems from any potential attacker. And I would make the argue that a 404 really isn't a problem with the application, it's just that the client requested something and it doesn't exist.
And I would make the argue that a 404 really isn't a problem with the application, it's just that the client requested something and it doesn't exist. And you can ask many security experts, you would probably get different answers, because well, you just would, but one of the prevailing thoughts is if this were a typical web application, we would return a 200, but we would have a page that says, you know, not found, something like that. In the case of an API, it's a little bit different, because the response is part of the payload. So it's OK, I think, for us to return a 404. So what we will do is return the error, and we'll just say that ticket's not found. We don't have to specify what kind of ticket or the ID or anything like that.
So what we will do is return the error, and we'll just say that ticket's not found. We don't have to specify what kind of ticket or the ID or anything like that. We can just say that it's not found, and we'll have a 404. So now let's try to send that request again, and we will see our, well, we see something that we shouldn't find, oh, findOrFail, yeah, OK, so findOrFail. That should fix that. So now we see that that ticket's not found, ticket cannot be found. Let's at least use, you know, at least some proper grammar there. OK, so we know that that doesn't exist, that's great. Let's try to delete a ticket that does exist.
Securing Show Error Responses3:44
OK, so we know that that doesn't exist, that's great. Let's try to delete a ticket that does exist. I think we created one with an ID of 103, so let's send that request. It was deleted, great. Let's try to send a request for that ticket. So we'll have 103 here, and, well, we get a 404, but once again, we get all of that extra information that we don't need. So let's do this. Let's go to the store, or the show method, not the store method, and let's wrap all of this within a try and catch.
Let's go to the store, or the show method, not the store method, and let's wrap all of this within a try and catch. In fact, let's just copy what we have for our delete method and paste that in so that I don't have to type all of that, and we might run into the same thing, yeah. So let's do this. For our show method, we will get the ticketID, and we will try to get the ticket with that ID, and we'll just do that right here. We don't need to change any other part of the code. We'll just do find, or fail this time, passing in the ticketID, and everything else should work fine.
Deleting Nested User Tickets4:42
We'll just do findOrFail this time, passing in the ticketId, and everything else should work fine. So if we send that request once again, we see that the ticket cannot, I just said this needs to be at least, there we go. Ticket cannot be found, okay, so let's, all right, okay, so that's working, okay. Let's move on, because we essentially need the same kind of functionality for the AuthorTicketController, because we need to be able to delete a ticket for a particular User in that case. So let's do the same thing here to where we will duplicate this POST request, and we'll of course modify it for the deleteUserTicket.
So let's do the same thing here to where we will duplicate this POST request, and we'll of course modify it for the delete user ticket. We need to change it to a DELETE request, and let's say that we want to delete the ticket ID of 45 for the user of 6. I have no idea if that's actually going to work, but this is going to give us the ability to at least start with that functionality. So let's open up our AuthorTicketsController, and let's just copy our destroy method from our TicketController, and we will use that as a basis, because really the only difference here now is that we have the author ID. So not only do we need to check if we have a valid ticket with that ID, but we need to
here now is that we have the authorId. So not only do we need to check if we have a valid ticket with that ID, but we need to make sure that the ticket belongs to that particular author. So the most straightforward thing that comes to my mind is this. If we have a ticket, we can check the userId to see if it is equal to the authorId, and if it is, then great. We will delete that ticket, and we will return OK. Otherwise, that ticket doesn't exist, because the URL is explicitly requesting a ticket that belongs to a particular user, and it doesn't. So we will just return a 404, which is all we need to do here.
that belongs to a particular User, and it doesn't. So we will just return a 404, which is all we need to do here. We don't need an else statement there. So that should work, and we do need a use statement here for the ModelNotFoundException, but that should work. So let's try this. We will send that request, and a BadMethodCallException. Error does not exist. It doesn't exist. We have that trait.
It doesn't exist. We have that trait. Oh, we never inherited the ApiController for our AuthorTicketsController. Well, that's an easy enough fix. We will inherit the ApiController. We can see that that ticket cannot be found. OK. So let's try to delete a ticket that does exist. So this will be the authorId of one, and I know that there is a ticket with an ID of 102 for that user.
So this will be the authorId of one, and I know that there is a Ticket with an ID of 102 for that User. So we should see a successful message for deleting that, and we do. Ticket successfully deleted. So that's basically it. We just need to check to make sure that the resource exists, and if it does, we delete it. If not, we return a 404. And in the case of a nested controller, we additionally check if the resource belongs to that particular User.
And in the case of a nested controller, we additionally check if the resource belongs to that particular User. If so, great. We delete it. Otherwise, we return a 404. So in the next episode, we can focus on editing our resource.
