در حال بارگذاری ...

Single Entry Routing0:41

Now, as always, we will tackle this in a series of steps. So up until this point, we had a direct mapping between a file path in the address bar and the corresponding controller. So for example, if I visit contact, well, we have contact.php, and sure enough, we have a corresponding contact.php controller. Okay, but I want to change all of that. Instead, I want a single point of entry where I can then be responsible for mapping whatever is in the URI to the corresponding controller. Okay, so I want to be in charge of that. Okay, so the first step is to create a new directory specifically for our controllers, like so. And I will grab about, contact, and index.php, and drag them into there. Okay, now we'll close that up. We'll have, again, a single point of entry that is responsible for handling the current route. So for example, if I say, hello there, and switch back, give it a refresh,

close that up. We'll have, again, a single point of entry that is responsible for handling the current route. So for example, if I say, hello there, and switch back, give it a refresh, sure enough, we are loading this page. And even if we have something like this in the address bar, notice that it still defers to that index.php file. Okay, well, next up, we learned in the last episode how to dd the current server super global. So let's import functions.php, and try that out again, dd($_SERVER); All right, come back, give it a refresh. And yeah, once again, we have the request URI. So notice if I change this to contact, yep, we have a match there. But we also have to be a little careful. For example, what if there happens to be something in the query string? You've probably seen this before, something like that, where we have a question mark at the end of the path,

Handling Duplicate Includes2:24

example, what if there happens to be something in the query string? You've probably seen this before, something like that, where we have a question mark at the end of the path, and then a series of key value pairs. Okay, well, now notice $_SERVER['REQUEST_URI'] is not /contact anymore. It is the full path, including the query string. So we need to account for that. Okay, but yeah, we could start by saying, okay, well, the current URI is $_SERVER['REQUEST_URI']. And then we could start in a very basic way. I could say, well, if the URI equals /, then maybe we're on the homepage. So we would require controllers/index.php. But now, before we run this in the browser, I do want you to notice something. This file requires functions.php. And then it potentially includes controllers/index. And that file also includes the functions file. And we can't do that. So in fact, if I come back to the browser,

functions.php. And then it potentially includes controllers/index. And that file also includes the functions file. And we can't do that. So in fact, if I come back to the browser, and we give this a refresh, we get a fatal error. Notice cannot redeclare dd. And again, that's because we require the file two times. So we effectively declared that function two times. Okay, so now we have the ability to remove this from all of our controllers. And I told you in the last episode, we would solve that little issue. And now we have. Great. So if I come back and give it a refresh, everything is working. We've handled the first use case. Okay, let's do another one. How about well else, if the URI is /about, then we will require controllers/about.php. Okay, but now real quick, before we run this, you may remember in our navigation bar, we are still linking to those full file names. Let's tweak it now. We no longer do .php

slash about.php. Okay, but now real quick, before we run this, you may remember in our navigation bar, we are still linking to those full file names. Let's tweak it now. We no longer do .php in the address bar. So I will delete all of those at once. Okay, so now we can say if you visit slash about, then let's load the corresponding controller. Cross your fingers, refresh, the home page works. I click on about. Oh, and we have that same problem. Maybe I didn't. I missed one. There we go. Sorry about that. I thought I got that. Anyways, we give it a refresh, and now it works. Okay, so you can see how we might begin building the most basic form of a router. And yeah, just to be comprehensive, we'll do the last one. If it happens to be slash contact, then I will load the ContactController. Yeah, so clearly what we have here isn't the final product, but we will slowly get there through baby steps. So again, home, about, contact. I think we're in

then I will load the ContactController. Yeah, so clearly what we have here isn't the final product, but we will slowly get there through baby steps. So again, home, about, contact. I think we're in good shape here. But yeah, now what about the query string? Maybe when you visit the contact page, you could include a name or something like that. Well, now at the moment, we don't see anything, and that's something we have to address. What if the User visits a URI that you don't have a corresponding controller for? What do we do in those situations? And we'll solve all of that in this video. But yeah, in this case, what is the problem? Well, URI is no longer /contact. It's this full thing here. And just to make sure we're all on the same page, I'll prove it to you. Come back, give it a refresh, and now this is what URI is equal to. So if we check it, is the URI /contact? Nope. So we do not load or require that controller. Okay, so it's almost

Stripping Query Strings5:46

Come back, give it a refresh, and now this is what URI is equal to. So if we check it, is the URI slash contact? Nope. So we do not load or require that controller. Okay, so it's almost like I need to say, no, no, no, no, let's strip off the query string. We may work with that later. But right now, I just want to know what the primary path is. So as it turns out, php offers a function called parse_url. You feed it a URI in this case, and it will parse it and separate the path from the query string. So let's use our handy-dandy dd function. I told you you're going to reach for it all the time. And if I give this a refresh, now notice I have an array with a key called path that is only the path, and that's what we want, and then another key called query that contains the query string. Perfect. This is just what we need. So now I'm going to wrap this whole thing in a call to parse_url, and now I want the value associated with the path key.

query that contains the query string. Perfect. This is just what we need. So now I'm going to wrap this whole thing in a call to parse_URL, and now I want the value associated with the path key. So we will grab that here. Okay, so once again, let's dd(variable), give it a refresh, and there we go. Even if we have something in the query string, we've only matched the portion of the URI that we care about. Great. So let's remove all of this, cross our fingers, give it a refresh, and now it works. Home, about, contact. But we're not done yet. Okay, so what we have here does work, at least right now, but it's kind of sloppy. So I think we need to refactor. And luckily, things like this are really easy to refactor once you know what to look for. So think about it. What we basically have here is a mapping. So if the path is this, then require this. If the path is this, then require that. If the path is this, then require

Refactoring Routes Map7:27

look for. So think about it. What we basically have here is a mapping. So if the path is this, then require this. If the path is this, then require that. If the path is this, then require that. So couldn't we represent that as an associative array if we wanted to? Something like this. We could say, well, if it's /, then load controllers/index.php. And then I'll duplicate that. If it's /about, then load about.php. If it's /contact, then load contact.php. So notice I've created a little map here, or you might even call it a lookup table, a way to associate a given URI with a corresponding controller. So why don't we name that routes like so? Okay, well, now that would allow me to get rid of all of this. And I kind of like how that looks. It makes it that much easier for me to add new routes in the future that I want to respond to and handle. But now, how do we require the correct value?

of like how that looks. It makes it that much easier for me to add new routes in the future that I want to respond to and handle. But now, how do we require the correct value? Well, think about it. I have a URI. And why don't I just check if that URI exists as a key within my routes array. So I might say something like this. And here's a new php function called array_key_exists. So notice you give it the key, in this case, it would be the URI. And then you give it to the array that you're looking into, in this case, routes. And what array_key_exists does is, well, exactly what it says. It lets you know if the array has a key of the given name that exists. So if we have a corresponding URI, only on that condition should we require the corresponding controller. Require routes URI. And let's see if it works. Home, about, contact, it all still works. So that was a successful refactor, or at least partially successful.

corresponding controller. Require routes URI. And let's see if it works. Home, about, contact, it all still works. So that was a successful refactor, or at least partially successful. And I say partially because, well, again, what if the User requests a URI that we're not yet responding to? Let's give that a shot. Let's see what happens. Maybe there's a typo or something like this. Well, now we get the white screen of death, and we definitely don't want that. So why is it white? Well, think about it. We grab the current URI. We set up our routes. We check to see if a URI exists in our list of routes. It doesn't. So we never trigger this logic, which means we go on here, and we don't do anything. So all we see is a white page. It all makes sense. Yes, but of course, we need to handle this use case. And generally, we want to provide what's known as a status code. So if you've ever heard of a 404 page, you can think of

Adding 404 Handling10:47

Maybe we want to let them know, uh-oh, something went wrong on our end, and we can't show you this page. Well, we might use a 500 status code for that. Another one might be, I don't know what you just requested. This page doesn't exist. In which case, we would provide a 404 status code. And as it turns out, that's the one we care about right now. Okay, so in php, we can set a status code by using http_response_code, and I will set it to 404. Then I will say echo, sorry, not found, and then let's die and kill the execution. Okay, so if I come back and refresh, yeah, now I at least have a little more feedback for the user. And more importantly, we are responding with the proper status code. If I bring up Chrome Developer Tools, or I'm sorry, Firefox DevTools, or I can right-click and choose Inspect, I can go to the console and give it a refresh. And yeah, notice right here, so the user made a request for this page, and the response

Firefox DevTools, or I can right-click and choose Inspect, I can go to the console and give it a refresh. And yeah, notice right here, so the User made a request for this page, and the response from my server is a 404 not found. We don't know what you're looking for, so we don't know what to do here. We're just going to give you some feedback there. Okay, but sorry, not found works. But maybe we can integrate it into our application just a little better. So what if instead, I require a file, like require views/404.php? And I will create that now. 404.php, and let's just duplicate some of this. So I will grab my index file and paste it in. And now this will say, sorry, page not found. And then maybe an anchor tag that sends the User back to the home page. Go back home. All right, and then I will style this real quick. Like, I don't know, text-xl, make it bold, and then maybe a little margin-top, and then I will style the link

to the home page. Go back home. All right, and then I will style this real quick. Like, I don't know, text to Excel, make it bold, and then maybe a little margin top, and then I will style the link like text blue and underline it. You know, something pretty basic. All right, let's give it a shot. If I come back and refresh, ooh, yeah, this is an issue. Undefined variable heading. And that's because while we're loading the banner, the banner expects a heading variable to exist, but it doesn't. So, of course, we get a warning. In this case, though, it's not overly appropriate to include the banner. So why don't I delete it in the case of a 404? Now if I come back and refresh, this is better. So now we have a page for home, and about, and contact. Or if the User visits some page that we don't know about, we provide the proper feedback. We respond with a 404, sorry, page not found, and we go back home. Okay, pretty cool. Let's get going. So back to index.php.

some page that we don't know about, we provide the proper feedback. We respond with a 404, sorry, page not found, and we go back home. Okay, pretty cool. Let's get going. So back to index.php. I think we can refactor this now. What do these three lines represent? They sort of represent us aborting the current request. So what if I create a function right here, and I call it abort? I could then take all of this, paste it in like so, and then here I can simply call abort. A nice little refactor, and everything's still going to work. As you see there. Okay, but often you will want to abort, but provide a different status code once you learn more about them. Maybe a 400, maybe a 500, maybe a 422. But right now we are hardcoding 404. Why don't we allow abort to accept a status code? We'll call it code, and then we will substitute it here. And here what I'll do is, remember, I need to wrap this in double quotes.

404. Why don't we allow abort to accept a status code? We'll call it code, and then we will substitute it here. And here what I'll do is, remember, I need to wrap this in double quotes if I want to inline this variable here like that. Okay, now really I should probably check to see, well, do we have a corresponding view for the current status code? Like, is there a 422.php file? I'm not doing that here because I'm just assuming I will never call it. But yes, in real life, you would want some safety mechanisms in place for things like that. But we're not going to worry about it. But now, yeah, I could pass through 404, and this is all going to work. Cool. But sometimes it's nice to say, well, the default is 404. And if you want to override it, you can, but the default is 404. So in these situations, I can set the parameter here to have a default by saying code = 404. So now if I don't pass a code, it will use 404, and this will work.

but the default is 404. So in these situations, I can set the parameter here to have a default by saying code = 404. So now if I don't pass a code, it will use 404, and this will work. But if I pass something else, like, again, 422, then code here is set to 422, and this is going to fail because, again, we don't have a corresponding view. And that's why in real life, we would want to handle that use case. But yeah, let's stay on track, and this all works. Pretty cool. Okay, what else can we do? Well, what about this block here? What is this doing? Well, it's routing the current URI to the corresponding controller. So maybe this could be its own function, like function routeToController. And then I could paste all of that in. But notice we have these squigglies because, well, within this scope, we don't have access to the URI and the routes. That's outside of the scope of this function. Okay, why don't we pass it in? Now I can call it

Extracting Router File17:01

this, this, and this, really all of this, is related to routing. And as you can imagine, in a real-life project, if you're not careful, everything gets dumped into this index.php file, and you end up with a lot of messy or spaghetti code. So an initial refactor we can do is simply move this to a file called router.php, and then I can require it. All right, let's do that now. router.php, and we paste it in. Okay, so now we have a dedicated file that specifically and exclusively handles parsing the current request URI and routing to the corresponding controller. Okay, so now index.php requires some functions for the app. It requires a router, and we're good to go here. So if I come back and refresh, yeah, once again, everything works like it did before, but now I think we're in really good shape.

RoutersStatus CodeCode Organization

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟