مرور درخواستهای HTTP و REST0:06
Welcome back. So no introduction at all. Let's jump right back in. So in the last episode, you are finally introduced to eloquence. And again, I hope you're so excited by this. I would say it's maybe the shining feature of Laravel. It's the best, it's the most intricate, it's the most useful feature that the framework provides. So I showed you how you can use the WIN method to conditionally apply constraints
So I showed you how you can use the WIN method to conditionally apply constraints to your queries, which is so cool. But in our case, I wanna keep it very simple. Just for now, let's bring it back to grab everything, whether there's five or 5,000, which you have to be careful about. Uh, we're just gonna grab all of them for now. Later you can learn about paginated uh, items, okay? So we now know that we can fetch all of our resource.
Index Route Convention0:43
Later you can learn about paginated uh, items, okay? So we now know that we can fetch all of our resource. And you know what? I think this is gonna help. Let's update the homepage to instead be our ideas endpoints. All right? So if I make a get request to slash ideas or any resource, whether it's uh, whether it's posts, excuse me, whether it's posts or articles or um, items, whatever, whatever it happens to be, it could be subscriptions, whatever you want.
or um, items, whatever, whatever it happens to be, it could be subscriptions, whatever you want. Um, it could even be something like this. Your watch later list could be a resource. So it's really quite flexible. But yeah, anyways, in, in our case, if I make a get request to a resource, that should retrieve all of them. If I make a post request to that same endpoint, that should store or persist a new one. And that's what we've done here. And then down here we have
that should store or persist a new one. And that's what we've done here. And then down here we have our little helper route that just flushes it out. We can update this to be idea and we're gonna call truncate. And that will basically delete all of the rows from that table. Okay, so I'm feeling pretty good here, but what about viewing a, uh, a single item for a resource? What would that look like? Well, why don't we copy this and think about it.
Show Single Resource2:01
What would that look like? Well, why don't we copy this and think about it. Are we making a get request, a post request? Well, if we are retrieving something, then it should be a get request, right? So we're gonna make a get request to ideas slash and then some kind of wild card, some kind of key, some kind of identifier. Often we will use the primary key, but it doesn't have to be that, just something
Often we will use the primary key, but it doesn't have to be that, just something that signals this idea from that idea. All right? So we have a couple options here. I think you're gonna like this. First of all, with a wild card, uh, with Laravel writing component, that Id will be captured. And if you want, it can be sent through to your closure here. So if I were to die and dump the id,
to your closure here. So if I were to die and dump the id, this would then be equal to whatever is referenced within the URI. Let's take a look. Let, let's go to Ideas slash one and we get one. If I did 299, then it's 2 99, which is cool. So yes, manually what we could do is say, okay, we now know the idea of the idea, the idea of the idea that we're trying to retrieve.
we now know the idea of the idea, the idea of the idea that we're trying to retrieve. So we could do something like this. The idea is idea, uh, find. And we're gonna provide the, uh, primary key. So this will find the corresponding id. It's kinda like the same as saying where the ID is, ID give me the first result, right? So notice first, by the way, uh, will give us a single record.
So notice first, by the way, uh, will give us a single record. And something like get, would give you a collection of records. It's important to know. But yeah, find is what most people would use. So once again, if I were to return the idea model from the route, that will be converted to JSON and excuse me, let's tweak this to one.
that will be converted to JSON and excuse me, let's tweak this to one. And sure enough, we see our corresponding object. Here's one, here's two. Okay. So now we have our idea and we can then send that to our view. Like this idea is idea and what should we name the view? Well, again, we could do it something like this, but instead we're working with a resource and I wanna follow common conventions in the community.
but instead we're working with a resource and I wanna follow common conventions in the community. So here's what we would do instead, if I open up my sidebar within the views directory, I'm gonna create a new directory that matches the resource name, in this case, ideas. Next, I'm gonna take this one here that's responsible for showing all of them. And often this is referred to as our index action and our index view.
And often this is referred to as our index action and our index view. So I will update this and rename it to index. Cool. We now have our index action. So if I come back to my routes file, I can change this to either Ideas slash index or more common, we can use dot notation, but it's the exact same thing. So if it helps you to think with a slash in the ideas folder,
So if it helps you to think with a slash in the ideas folder, grab this file right here, you can do it. But again, very common. And what I would do is dot notation, um, behind the scenes, it's just gonna replace it with a slash so it does the exact same thing. Cool. So now I can think of this sort of like, for a resource, this is my index action. Okay, what about this one?
for a resource, this is my index action. Okay, what about this one? Well, this is where we show an idea, right? I can think of this sort of like my show action. So I'm gonna change the view name to Ideas show. All right, let's go ahead and create that show Blade PHP. And to start, I'm gonna steal some of this, but we don't need most of it. Uh, so right down here, we don't need a form, and we're not looping over a collection.
Uh, so right down here, we don't need a form, and we're not looping over a collection. We're really just displaying a single idea. So yeah, something like this, just for now, uh, this could be, uh, let's do it within a diviv, the idea description. So it's not gonna look very pretty, but sure enough, we should be able to view an idea now. So if I come back, give it a refresh, sure enough, we can see the show page for just one idea.
So if I come back, give it a refresh, sure enough, we can see the show page for just one idea. And yeah, why don't we say MT six? Cool, let's go to the idea with a idea of one, start a podcast. But what if there is no idea, uh, or ID in the database, then you're gonna get an error, right? So be careful about this. 'cause this is something that can happen.
So be careful about this. 'cause this is something that can happen. We try to request, um, the show page, but there is no corresponding table record. So let's see what the issue is here within my ROS file, we tried to find an id, uh, idea, but if none was found, actually Noll is returned. So in our example, right now, idea is set to null, and then we load a view and we pass through null as this idea variable.
and then we load a view and we pass through null as this idea variable. Then we try to say effectively null, uh, description. And of course, you can't interact with null as if it were an object. That's going to lead to an error, right? So if I come back, we get an error. You're trying to read a property description on null, okay? So this is where it gets fun.
Handling Missing Records6:53
You're trying to read a property description on null, okay? So this is where it gets fun. Of course, we could manually do a check and we could say, well, all right, well, if idea is null, then we're going to abort with a 4 0 4, A 4 0 4 not found. And this will do the trick. And this provides some protection. If we get to this point right here, that means there was a, a, an a relevant idea in the database. Alright? So if I come back
a, an a relevant idea in the database. Alright? So if I come back and give it a refresh, we get a 4 0 4, this is better. If we access an idea that does exist, then uh, we never hit this point and we continue forward. However, you can imagine that we would have to do this a lot, right? Um, if we need to edit an idea, we would try to find it and we would check if it's null and then aboard. Uh, what about the action
and we would check if it's null and then aboard. Uh, what about the action to update the idea in the database? Once again, find the idea and see is there a relevant one, if not aboard. This is a very common pattern and flow. So instead, LAR law makes this quite a bit easier, and I'm gonna show you this in two steps. First, instead of running find, I can replace this. And I I just wanna show you the before and the after.
First, instead of running find, I can replace this. And I I just wanna show you the before and the after. So if I come back and we access one that doesn't exist, we get the error, right? But if I tweak this to find or fail, if I come back and give it a refresh, now Laravel will automatically handle this and it's, it's gonna do basically what we just did. It's gonna try to find the record with this id, but if it couldn't find one, it fails, it aborts and it returns a 4 0 4 response to the user.
but if it couldn't find one, it fails, it aborts and it returns a 4 0 4 response to the user. So again, so much of Laravel is taking verbose code that you normally would write by hand and wrapping it up into one or two lines. It's what I really love about it, okay? But now we're gonna simplify this even further, and this is gonna blow your mind. So we're gonna leverage something known as route model binding.
Route Model Binding8:46
So we're gonna leverage something known as route model binding. And that sounds a little scary at first, but it's, it's really not so bad at all. Just break it down in your head route, okay? One of these things right here, model, okay? Your eloquent model and then binding a connection. So we are binding, uh, an eloquent model to a particular route. So think about it. If we have ideas slash one,
to a particular route. So think about it. If we have ideas slash one, and we want an idea instance, labelable smart enough to just put two and two together and figure out, okay, you want me to find the idea that matches, uh, this wild card here, right? So here's what we do. I'm gonna change this wild card name to idea, and then I'm gonna add a type, and that's just, um, the, the type of the model that I want. And this case it's idea.
and that's just, um, the, the type of the model that I want. And this case it's idea. So I'm basically asking Laravel, when it calls this, uh, function right here, I want Laravel to give me the idea that I care about. How cool is that so that I don't have to manually do this? Neat, right? So, cool. It's, it's ridiculous how cool it is, uh, even after all of these years. So here's an important thing to be aware of.
after all of these years. So here's an important thing to be aware of. First, I'm gonna prove it to you. I'm gonna die and dump the idea and view it in the browser refresh. And sure enough, I can see it looks like we have idea slash one, and here is the corresponding data. Let's do idea slash two or ideas slash something that doesn't exist. And we still get a 4 0 4. So Laravel still handles that.
or ideas slash something that doesn't exist. And we still get a 4 0 4. So Laravel still handles that. But if we provide two here and we switch back, think about it when this gets resolved, this is basically this, and Laravel sees, okay, what you actually want is an idea model. So I'm just gonna find the idea with an idea of two because this is clearly what you want, okay? Now, one thing you need to be aware of is that this wild card name
Now, one thing you need to be aware of is that this wild card name and this parameter name are the same. So if I were to say something like this, the idea, this is not gonna work. So if I come back and refresh, I will still get an empty model instance. But notice that the attributes are blank. So it, it's, it's effectively saying new idea, it's not gonna work.
So it, it's, it's effectively saying new idea, it's not gonna work. We want these to match up. That's one of the things that the framework is checking for. And it's how it knows what you're actually requesting. It's ridiculous, right? It's just so incredibly cool. It blows my mind. Okay? So now this is gonna pay so many dividends, I promise. Uh, what about a page two, edit an existing idea. Well, that page should display a form, right? Let's do it.
Edit and Update Flow11:16
Uh, what about a page two, edit an existing idea. Well, that page should display a form, right? Let's do it. Now, let's create a new endpoint, and this will be our edit action, and that's gonna load an edit view. But notice the URI, hmm will need to be tweaked. So what's a good endpoint for that? Well, this is our resource. This is a single resource or a single, uh, item there. And then let's add edits.
This is a single resource or a single, uh, item there. And then let's add edits. This is to edit this specific item. Alright, we got it. And again, notice I just ask for the idea. I don't have to manually create a query, I just ask for it and uh, I shall receive. Alright? So let's create the view. I will duplicate index to save ourselves some time. And let's see, I'm not looping over it. So let's get rid of that. At the top,
And let's see, I'm not looping over it. So let's get rid of that. At the top, we'll say edit your idea. Uh, we can make the button say update and clear that out. And let's see what, let's see how we're doing so far. Let's come back and we'll go to ideas slash two slash edits. And now we have a form to edit our idea, but the text area is empty, so let's set the value equal to the ideas description, and now it's populated.
the value equal to the ideas description, and now it's populated. Okay, so now let's return to rest a little bit. When I click this update action, what exactly should take place? Well, am I making a get request to update an idea? No, that doesn't make sense. I'm not retrieving anything. Uh, should I make a post request? Well, no, uh, restfully, that's, that's used more for creation.
Well, no, uh, restfully, that's, that's used more for creation. So if I instead want to update an existing resource, I should use a patch request. But I can't do this, right? Uh, browsers out of the box only support get and post. And in fact, you can see a squiggly line here, it's not gonna work. So instead we're gonna leverage something known as method spoofing.
So instead we're gonna leverage something known as method spoofing. This is basically where we say, okay, well I have to do post because that's all browsers understand. But I wanna signal to Laravel that the request method that I'm actually trying to signal to you is patch. And we do that via a method directive, as you see here. So like CSRF, this will expand to a hidden input where we specify what the request type should be. And then once again, behind the scenes,
where we specify what the request type should be. And then once again, behind the scenes, this happens without you noticing a thing. By the way, larva will inspect this request, it will see that it's included and it will know, okay, I see you used post, but you actually wanted patch. So I'm gonna make sure that I route the request accordingly. Okay, so let's take a look. Now if I come back, refresh, let's open up our form. And now we have a hidden input for our CSRF protection.
Now if I come back, refresh, let's open up our form. And now we have a hidden input for our CSRF protection. It includes our token, and then we have a new one for our method spoofing. Bel, I know one made a post request, but treat it like a patch request, please. Cool, so what should our endpoint be? Well, this is the great thing. We're following this URI convention. It's gonna be the ID of the idea.
We're following this URI convention. It's gonna be the ID of the idea. Alright, so if I come back to my route's file, we're now gonna have a new one here to actually update the resource. So notice that this gets broken into two steps. We would have one route to edit the resource, but that's not actually persisting it, that's just showing the page to perform and specify the edit.
that's just showing the page to perform and specify the edit. And then when you submit that form, then we're gonna make a patch request, and this will be our update action. So notice the URI, the same, the same, the same. Notice the conventions that we're following here. So to update it, what do we do? Well, we're not rendering a view, we are asking for the idea. And then check this out.
we are asking for the idea. And then check this out. I can just say idea, update it, and how do we want to update it? Well, I think we're just changing the description and I will reference that from the request. Once again, we're not yet doing validation, even though we should. Uh, I want, I want to, I want to dedicate a full lesson to that.
Uh, I want, I want to, I want to dedicate a full lesson to that. So for now, we're just taking the happy path, which is a little bit dangerous, but that's okay. Okay, so now I have an endpoint to update, uh, an existing idea. And when we're done, where should we go? Should we redirect back to the homepage? Should we redirect back to the show page? And again, just pick what you want.
Should we redirect back to the show page? And again, just pick what you want. I think in this case, why don't we redirect back to the show page so we can say, return a redirect back to ideas slash and then, uh, the id and yeah, we can use concat Nation like this or, or of course, if you want, we could use string interpolation, whatever you want. All right, so let's give it a shot, refresh, build
we could use string interpolation, whatever you want. All right, so let's give it a shot, refresh, build an incredible, uh, old fashioned cabin, update it. Oh, and you know what I'm teaching you and I'm getting everything wrong. What did I do wrong here? Uh, update ideas, set description. What did I do wrong? I think I know if I switch back, actually, it's always good to debug these things together.
I think I know if I switch back, actually, it's always good to debug these things together. So yes, in this case, uh, we're still using the old name where we just set a two ideas specifically. Let's tweak this to be description. So in fact, we're gonna update all of these references here, and then I'm also gonna return to the index page and make sure that we do the exact same thing. Mm-hmm. And then back to my rounds file when I persist, we will update this link.
Mm-hmm. And then back to my rounds file when I persist, we will update this link. So, and hopefully you understood what we were doing there. We're just changing the name of the inputs. Okay, let's come back, give it another shot, build an amazing cabin, update it, it updates it in the database and it redirects. And sure enough, we see build an amazing cabin and then and table plus. All right, refresh. And sure enough,
and then and table plus. All right, refresh. And sure enough, it's reflected in the database as well. I love it. Alright, so let's keep going. We started with our index action, our show action. And by the way, there's a method to the madness why I'm naming these in such a way. Uh, we have an edit action, we have our update action. This one, uh, we often call this the store action. We are storing a a new resource within the database.
Deleting Resources17:46
This one, uh, we often call this the store action. We are storing a a new resource within the database. And then finally, yeah, like I said, this is temporary. In fact, I'm gonna delete, uh, I will delete this entirely to not confuse you, but we do need the ability to delete, um, a single idea. So let's just do the exact same thing again. I'm gonna copy as much of this as I can. This will be our destroy action because often delete is a, uh, a special keyword.
This will be our destroy action because often delete is a, uh, a special keyword. So we're gonna respond to a delete request. Again, just in your head, if you can't remember which request type to do, just break it down. And you know what, uh, purists don't like this, but generally rest, uh, translates to crud. So if you make a post request, you're creating, right? If you make a get request, you are reading.
So if you make a post request, you're creating, right? If you make a get request, you are reading. If you, uh, make a patch request, you're updating. And if you make a delete request, you're deleting. So again, purists, there's a lot more to rest than just that. But when you're first learning, it's a simple mapping that you can form in your head. So in our case, if I want to delete a specific idea, then I would make and respond to a delete request.
So in our case, if I want to delete a specific idea, then I would make and respond to a delete request. Alright, once again, let's ask for the idea that we're trying to delete and check this out. I'm just gonna say idea, delete. And then let's return to, um, the page where we fetch all of the ideas. It's so good. Alright, so where do you want this, uh, delete button to be displayed? Well, why don't we do this When we show a an idea,
uh, delete button to be displayed? Well, why don't we do this When we show a an idea, let's also include an edit button. And then when you click on that, we should have a delete button on that edit page. Alright, let's do it. So let's go up to our show action. Let's load the view down here at the bottom. Let's have an anchor tag that says edit. And there it is. Uh, but actually, why don't we use one of these buttons.
And there it is. Uh, but actually, why don't we use one of these buttons. Now, of course, we could extract these into their own components so that you're not repeating all of these classes. Um, but we can grab some of this and we'll say is ideas slash and then the current id, that's the identifier for the one we want to edit. Come back, refresh. Good MT six,
that's the identifier for the one we want to edit. Come back, refresh. Good MT six, give some space, it's fine. Okay, so now I can click edit and that will take me, oh, sorry, ideas slash the identifier slash edit. Alright, so now we see a form to edit it. Good, but let's also include a button to delete it. So let's go to our edit view. And then right down here, let's add another button
So let's go to our edit view. And then right down here, let's add another button to delete it. And maybe, let's see, let's make the background color red or something like that. All right, looks good. Maybe reduce the gap. You get the idea. So now this is a common, uh, point of confusion for people learning is you wanna include the delete button, but now the delete button is housed within a form that's already making a patch request, right?
delete button, but now the delete button is housed within a form that's already making a patch request, right? So that means if I click delete, it's actually going to submit the form and make a patch request and update the idea rather than delete it, right? So let's fix this. Click update. Yeah. So instead we wanna create a brand new form, but now you're thinking, well, I'm not allowed to do this, right? This is what everyone runs into.
I'm not allowed to do this, right? This is what everyone runs into. Well, I can't have a form within another form that that's not allowed. So yeah, it's, it's very simple. Here's what you do. Um, if you're not using JavaScript, just create a second form below the first one. And this is your delete form. So the method is, and delete, nope, can't do this, right? 'cause the browsers only understand, get and post.
So the method is, and delete, nope, can't do this, right? 'cause the browsers only understand, get and post. So you say, all right, post and then signal to Laravel that what you actually meant was a delete request. And then don't forget, for if or for any kind of patch or delete request, you need the CSRF protection in place and a post request. So we're gonna use our CSRF hidden inputs. And this can just be, uh,
So we're gonna use our CSRF hidden inputs. And this can just be, uh, other than this an an empty form, right? We have everything we need other than action, which would be ideas slash and then the id. Okay, so we now have this button and I wanna say, all right, when you click on me, I actually want it to point to this form rather than the form that it's within. And we do that via the form attributes.
to this form rather than the form that it's within. And we do that via the form attributes. We're gonna give it the, the ID of the form that we are triggering. Basically, why don't we call this delete idea form? And then I will add an idea here. That's it. So think about it. When I click on this, it's gonna make a delete request to this endpoint. So let's find where that's computed or created
request to this endpoint. So let's find where that's computed or created or registered. And that's right here. Delete request to this endpoint that will receive the idea using wrap model binding. It will delete the idea, uh, and then it will redirect back to all of the ideas. All right, let's give it a shot. Build in a mason cabin, delete. And now it's gone. We redirect back and we don't see it anymore.
Build in a mason cabin, delete. And now it's gone. We redirect back and we don't see it anymore. Let's do gibberish. Save. Let's, um, view it. And actually we should make these clickable, but that's okay to, what is it? Uh, there it is. Uh, edit. We can change it with update or we can delete it entirely and it's gone. Alright, so 30 seconds and we're done. Let's go into the index action. Here's all of our ideas.
Alright, so 30 seconds and we're done. Let's go into the index action. Here's all of our ideas. We're gonna turn these into anchor tags that link to, uh, the respective idea, which would be ideas slash the identifier. Come back, refresh. And now it's not styled, but I can click on this to view it. I can edit it, start a great podcast. I can update it and then finally I can delete it entirely. You are learning so much, trust me, ladies and gentlemen.
I can update it and then finally I can delete it entirely. You are learning so much, trust me, ladies and gentlemen. This is the bedrock of so much of what we do. Uh, as web developers, we're often just crud monkeys and there is definitely, uh, a correlation between crud and rest, even though there's quite a bit more to it. Okay, so now I want you to focus on these action names. It's really important and do your best to memorize it. Um, play a game in your head, close your eyes and say one of these action names show.
Um, play a game in your head, close your eyes and say one of these action names show. What would I do for the show? Action? I would show a resource. If you're dealing with posts, I would show a post. Alright, what would you do for the edit action? Oh, I would show a form to edit the post. Okay. What would I do for the store action? Oh, well this is the one where I receive some data and I actually persisted to the database.
Oh, well this is the one where I receive some data and I actually persisted to the database. Just do that over and over and get super comfortable and all of that is gonna pay off in the next episode.
