WEBVTT

00:00.200 --> 00:00.770
Okay, guys.

00:00.770 --> 00:05.090
So in this video I'd like us to have the router class implemented.

00:05.120 --> 00:09.560
We're gonna be implementing it from bottom to the top.

00:09.590 --> 00:16.400
Additionally, I'd like to have a separate routes file where we're gonna be adding routes using this

00:16.430 --> 00:17.390
add method.

00:17.390 --> 00:25.130
And the way we're gonna implement routing would probably be the closest to how it's done in the Laravel

00:25.130 --> 00:26.060
framework.

00:26.090 --> 00:32.000
Now, I generally do think that the router is a complex piece of code.

00:32.030 --> 00:34.310
So you would need to focus.

00:34.310 --> 00:39.530
And also I think you're gonna learn some interesting tricks and practices.

00:39.530 --> 00:48.560
And I think it is also very useful to just try and solve a complex problem, which definitely the routing

00:48.560 --> 00:49.460
is.

00:50.060 --> 00:54.110
So maybe let's start from this call action method.

00:54.110 --> 00:58.760
In this method we would like to create a class.

00:58.760 --> 01:07.650
The controller class that we point to in this controller string and call a method of this class, which

01:07.650 --> 01:09.840
also is passed as a string parameter.

01:10.020 --> 01:11.970
So that's interesting.

01:11.970 --> 01:16.140
We haven't done anything like this before.

01:16.170 --> 01:22.680
Now let's see how can we create a class by just having the class name, the controller class name,

01:22.680 --> 01:25.560
and the action name, which is a method.

01:25.920 --> 01:32.700
So first let's figure out the namespace of the class.

01:32.700 --> 01:37.770
So we know that the app code will be stored inside the app folder.

01:38.310 --> 01:44.730
I'm going to create a controller folder inside because this is where we're going to be keeping the controller

01:44.730 --> 01:45.840
classes.

01:46.170 --> 01:52.560
Let's quickly jump to Composer.json to remind ourselves that inside the app directory, the namespace

01:52.560 --> 01:54.540
prefix is app.

01:55.830 --> 01:58.770
Okay, so we can start with the app prefix.

01:58.800 --> 02:05.140
Now I'm adding two slashes because one slash is an escape character for special characters.

02:05.440 --> 02:14.770
Then we go with controller namespace again slash, and only then we've got the actual controller class

02:14.770 --> 02:18.910
name, and I can directly use this controller variable here.

02:19.120 --> 02:21.430
So this would be our class name.

02:21.430 --> 02:27.760
Now what's interesting is I can create a new class in PHP by using a variable.

02:30.220 --> 02:35.350
So in this place PHP will just figure out what's the value of this variable.

02:35.350 --> 02:39.910
It will try to find the class using this name using autoloader.

02:39.910 --> 02:44.170
And if it succeeds it will just create this controller class.

02:44.170 --> 02:48.760
So I would just need to create a specific controller class first.

02:49.600 --> 02:55.450
Now, I've said previously that action is a method of a controller.

02:55.450 --> 03:01.120
That's why I can also use the action variable in place of the method name.

03:01.120 --> 03:09.170
Again, PHP will resolve the value of this variable, and whatever the name is, it will try to find

03:09.200 --> 03:13.400
such method in this created object and run it.

03:13.430 --> 03:17.060
Okay, but controllers can also have some parameters.

03:17.060 --> 03:18.590
What do we do about that?

03:18.650 --> 03:27.350
Finally, let's use array unpacking using the params, which is an array, because we're going to collect

03:27.350 --> 03:34.070
the passed parameters of every defined route in the order they were defined.

03:34.070 --> 03:41.210
And that's also a requirement of our method that it should have those parameters defined in the same

03:41.210 --> 03:45.080
order as we can find them in the route.

03:46.100 --> 03:46.940
I need to fix this.

03:46.940 --> 03:51.110
This is return and this method is complete.

03:51.110 --> 03:55.640
This is how we're going to be calling the specific controller method.

03:55.640 --> 04:01.520
Once we are able to identify the route and was its matching controller.

04:01.520 --> 04:04.830
So let's go to the match root method next.

04:05.460 --> 04:08.610
Now this match root method has only one job.

04:08.610 --> 04:12.690
Its job is to compare the root URI to request URI.

04:12.720 --> 04:18.780
Now this means that we're going to run this for every single root we have defined, unless we earlier

04:18.780 --> 04:20.460
find the proper root.

04:20.640 --> 04:22.890
So here is a reminder.

04:24.180 --> 04:30.390
So first we need to divide all those URIs into segments.

04:31.080 --> 04:34.920
So as you see those two will match in our case.

04:35.010 --> 04:36.840
So we've got the static part.

04:36.870 --> 04:38.010
We've got a parameter.

04:38.010 --> 04:39.510
And this is matching.

04:39.540 --> 04:45.930
That's why first let's cover dividing those URIs into segments.

04:45.930 --> 04:48.720
And the segment separator is a forward slash.

04:49.560 --> 04:49.800
Okay.

04:49.830 --> 04:53.940
So let's define a variable called root segments.

04:53.970 --> 04:57.570
We're talking about the current root that we are processing.

04:57.570 --> 05:01.530
And another one would be the request segments.

05:01.530 --> 05:03.120
So we can compare them.

05:04.080 --> 05:07.950
Okay, so I've said that the forward slash is a separator.

05:07.950 --> 05:13.380
And in PHP to get the strings separated by something we use explode.

05:13.590 --> 05:15.420
This is our separator.

05:15.420 --> 05:18.690
And I'm going to stream to remove Whitespaces.

05:18.690 --> 05:21.900
So first I'm using the root URI.

05:21.900 --> 05:28.350
And additionally when using trim to remove white spaces I can remove some additional characters like

05:28.500 --> 05:30.510
the forward slash itself.

05:30.540 --> 05:37.140
Now, you might have guessed that we're going to call the same function for the request URI.

05:37.170 --> 05:39.060
Just need to fix the name here.

05:39.090 --> 05:41.100
That's request URI.

05:41.130 --> 05:42.990
Okay, we've got the segments.

05:43.440 --> 05:47.580
So the algorithm let's take a look at it.

05:47.610 --> 05:53.580
We need to first see if we have the same segment count and then match individual segments.

05:54.810 --> 05:58.920
So the count of arrays because those will now be erased.

05:58.920 --> 06:00.960
The root segments and request segments.

06:00.960 --> 06:06.670
We can just compare the result of count of route segments.

06:06.700 --> 06:13.360
If it's different than the count of request segments.

06:13.390 --> 06:17.620
If it's different, we return null and null in.

06:17.620 --> 06:28.450
This function is used to return that we haven't matched the actual route URI to a defined route, because

06:28.450 --> 06:32.530
if we would match it, then something would be returned in the array.

06:32.530 --> 06:38.560
And this something is either an empty array or list of all the found parameters.

06:38.590 --> 06:47.200
Now, if we don't eliminate this right route right away, then let's add the params variable, which

06:47.200 --> 06:52.810
would be an empty array and then return it.

06:52.810 --> 06:56.920
But first we need to go through every single route part and compare it.

06:56.950 --> 07:03.490
Okay, so let's use a for each loop to go through all the route segments.

07:03.490 --> 07:09.320
Immense and let me get the index as it might be handy.

07:09.320 --> 07:13.220
And then we've got the route segment.

07:14.390 --> 07:20.090
Okay, now our first job is to check if this segment is a parameter.

07:20.090 --> 07:21.470
How can we do that?

07:21.770 --> 07:24.230
Some extra functions in PHP.

07:24.830 --> 07:34.010
So one is called str startswith where we can check if the root part which is haystack.

07:34.040 --> 07:42.500
That's the parameter name starts with curly brace opening because this is how we begin a parameter.

07:43.370 --> 07:47.840
And also we check if the same string ends with.

07:47.840 --> 07:55.010
So there is another function called endswith where haystack is also the root part.

07:55.730 --> 07:59.000
And here we are looking for a closing brace.

07:59.030 --> 08:04.320
Now if that would be the case then we just add a parameter.

08:05.550 --> 08:07.110
So two parameters.

08:07.140 --> 08:14.490
We're going to add the parameters using the parameters defined name which we can get from the root part

08:14.520 --> 08:16.740
excluding the curly braces.

08:16.740 --> 08:21.390
So we can just use trim get the root part.

08:22.200 --> 08:26.640
And what we exclude is white spaces and curly braces.

08:28.740 --> 08:33.660
And the value of it is the request.

08:35.880 --> 08:37.110
Segments.

08:37.890 --> 08:40.740
And this is where we needed the index.

08:41.310 --> 08:45.600
So that's the root part I've used the wrong name.

08:45.600 --> 08:48.810
This is the root segment okay.

08:50.730 --> 08:53.850
So again this is a parameter.

08:53.850 --> 08:58.110
It's always starting with a curly brace and ending with a curly brace.

08:58.110 --> 09:02.910
So everything inside it is the parameter name.

09:02.910 --> 09:10.660
That's why here we are trimming white spaces and curly braces by using the root segment, which is from

09:10.660 --> 09:12.160
the root definition.

09:12.340 --> 09:15.880
And that's the key to the parameters.

09:15.880 --> 09:23.650
And then as a value, we use the segment at the same place from the request which will contain this

09:23.650 --> 09:25.150
parameter value.

09:25.180 --> 09:28.360
So that's the first condition that we have for a segment.

09:28.870 --> 09:34.660
Another one is checking if maybe the static segments don't match.

09:34.660 --> 09:42.160
Because if we don't have a parameter then this means we have a static segment that's a static segment

09:42.160 --> 09:45.970
like the text that is saying literally posts.

09:46.000 --> 09:47.890
That's just an example.

09:47.920 --> 10:02.680
So if the root segment is different than the request segments with the given index, remember we can

10:02.710 --> 10:09.920
safely use the Indexes for both arrays because first we have checked if they have the equal.

10:09.950 --> 10:12.290
Length and if that's the case.

10:12.290 --> 10:17.900
So if the static segment has a mismatch then again we can return null.

10:17.900 --> 10:23.720
This means that we didn't have a match and this route just doesn't match.

10:23.720 --> 10:30.710
So maybe this is a little bit complex because it is a kind of an algorithm.

10:30.710 --> 10:38.810
But anyway I think we really need to practice all kinds of problems and solving them anyway.

10:38.810 --> 10:41.540
This should match one specific route.

10:41.540 --> 10:49.880
And now our job is to call this match route function for every defined route that we have inside the

10:49.880 --> 10:50.480
app.

10:51.890 --> 11:00.770
Next up, this find route method will use the match route method to compare all the routes defined to

11:00.770 --> 11:03.920
the current URI and the method.

11:04.830 --> 11:09.450
So let's use foreach again going through all the routes.

11:12.330 --> 11:18.870
And then we are calling this match route and we are getting the parameters.

11:20.610 --> 11:25.980
So here we'll be passing the route URI.

11:30.810 --> 11:33.240
And the URI of the request.

11:33.240 --> 11:35.190
So we are comparing those.

11:35.190 --> 11:43.650
Now the result as you might remember if we get anything else then null it means we have found a matching

11:43.650 --> 11:44.550
route.

11:45.810 --> 11:47.250
But that's not everything.

11:47.250 --> 11:53.430
So first we need to check if params is different than null.

11:53.970 --> 11:58.080
This means we've got something that is almost what we are looking for.

11:58.080 --> 12:03.030
But remember that we've also got a method and this wasn't checked anywhere.

12:04.840 --> 12:12.790
So it needs to match the expected method of the request that's either Get or post or whatever you'd

12:12.790 --> 12:13.900
like to use.

12:14.380 --> 12:22.090
Only then we can return something from Findroot method, which as you see, is also a nullable array.

12:25.600 --> 12:34.030
So we go through every single route and if we can't match anything, then we just return null from this

12:34.030 --> 12:34.840
method.

12:35.470 --> 12:43.990
But we need to tell the dispatch method what is the name of the controller class and the action as well.

12:44.020 --> 12:51.610
That's why from this find route method, we're going to return all the info about the route itself,

12:51.610 --> 12:54.940
about this route we are currently investigating.

12:56.980 --> 13:01.480
And only then we're going to add another parameter called params.

13:01.570 --> 13:07.280
Getting the parameters that were passed through this route.

13:08.780 --> 13:15.530
So at this point, it might be getting complicated why we construct this return type this way, but

13:15.530 --> 13:21.500
we are just returning all the data that will be required in an array.

13:21.860 --> 13:30.320
So maybe it would be more clear once we see that this add method is adding routes that have the method,

13:30.350 --> 13:32.510
the URI, the controller.

13:33.230 --> 13:37.160
So basically here we are returning those three values.

13:37.160 --> 13:39.500
The method that you write the controller name.

13:39.500 --> 13:42.980
Plus we are adding the parameters on top of it.

13:43.160 --> 13:48.950
Maybe it will make sense if I just implement the add method right now.

13:49.070 --> 13:53.810
So we can add two routes by using this square operator.

13:54.800 --> 14:04.670
And every item is an array itself where we've got the method which equals method.

14:04.670 --> 14:12.200
Then we've got the You or I, which also equals the value of your variable and the controller.

14:12.230 --> 14:20.000
You can also optionally replace this with a call to a compact function, which I've probably used before.

14:20.030 --> 14:22.250
So this is how a route looks like.

14:22.250 --> 14:24.380
It has a method you write controller.

14:24.410 --> 14:32.840
So basically in this place where we return the response from find route, we're going to be getting

14:32.840 --> 14:40.100
those three elements of the array plus the parameters that we got from the actual URI.

14:40.130 --> 14:41.120
Okay.

14:41.600 --> 14:47.120
Next up we've got the final step the dispatch function.

14:47.240 --> 14:56.360
So here our job is to just find the route for the URI and the method that we received.

14:56.390 --> 15:02.270
If we've got a null so it wasn't found it might happen.

15:02.270 --> 15:10.770
If someone enters an incorrect URL we can return the result of not found method.

15:11.190 --> 15:18.930
This doesn't exist yet, but we can easily copy this from the previous code.

15:23.160 --> 15:25.290
So let me just quickly add this.

15:25.290 --> 15:30.450
This is public function not found.

15:31.410 --> 15:34.260
For now, let's just echo this text not found.

15:34.260 --> 15:38.280
We're going to be changing that to an actual view later on.

15:38.370 --> 15:43.830
And the final thing here is to call the controller and the action.

15:44.550 --> 15:48.420
So we can use array destructuring and call explode.

15:48.960 --> 15:55.080
Because this directly stems from how we're going to be defining the controller.

15:55.080 --> 15:57.540
So let me show you how we're going to do that.

15:57.630 --> 16:02.580
So when we point to a controller let it be a post controller class.

16:02.670 --> 16:05.880
The action will be marked after an at sign.

16:05.880 --> 16:13.450
So this would should be index action in post controller class or this example.

16:13.480 --> 16:17.590
Here would be a show action in post controller class.

16:17.590 --> 16:21.250
So that's the name of a method inside this class.

16:21.250 --> 16:27.580
That's why with explode I'm going to use the at sign up separator.

16:27.580 --> 16:35.230
And from root controller we are getting the controller class and the method name the action.

16:35.980 --> 16:45.670
So with destructuring I'm getting separately the controller and the action because this will just return

16:45.670 --> 16:47.410
an array with two items.

16:47.410 --> 16:48.970
So that's the first item.

16:48.970 --> 16:50.410
That's the second one.

16:51.340 --> 17:03.850
And finally we return the result of this call action which accepts the controller, the action and the

17:03.850 --> 17:08.960
parameters which we get from the route under the key palms.

17:08.990 --> 17:15.650
Now the logic is complete and it's time that we define some roots and try this out.

17:17.060 --> 17:23.510
Okay, so since this is a pretty long lecture, I think we might take a short break and do it in the

17:23.510 --> 17:24.410
next one.

17:24.440 --> 17:27.620
For now, let's just quickly review what we have done.

17:27.620 --> 17:31.460
So using this add method you can add more roots.

17:31.820 --> 17:33.590
This is a not found function.

17:33.590 --> 17:36.650
We had a previously something very similar.

17:36.680 --> 17:44.420
But the main entry point to this class is the dispatch method to which you pass the URI and the method.

17:44.420 --> 17:52.700
It then tries to find a root and call the specific controller if obviously one is found.

17:52.700 --> 18:00.380
So here we dynamically create a class and try to call its method also dynamically by using a variable.

18:00.380 --> 18:03.830
So maybe this was something we haven't done before.

18:03.830 --> 18:08.090
And I think it's interesting to know that this is possible.
