Okay guys, so it's time to create and run some middleware so we can see how it all works.
So let me jump to directory structure and we're going to create Middlewares inside app folder.
Let me create a folder called Middlewares to use our convention of plural names.
And the first one can be called view or just view middleware.
It's up to us how we call those classes.
So let me call this just view.
This is our first middleware.
Now let me quickly explain what this is going to do.
First I'm going to add the namespace.
This is app Middlewares.
So we've got our front controller which shares the currently authenticated user as a global view variable.
And from the lack of a better place, we just have put that into the front controller I think this is
the best use case, or that's an ideal use case.
To put it differently, for a middleware that's global, that always has to run because we're going
to need this always.
So that's the first thing I'd like to move to a middleware.
And that's why I've created a view middleware which will just do exactly that.
Class name will be view same as the file name.
And it needs to implement our middleware interface.
To which I'm gonna jump next because we need to implement this handle method.
It's super important to remember that the whole logic of middleware depends on the next target to be
called, which we need to call inside this middleware so that this chain doesn't get broken unless we
want it to.
Like in this example.
So in here I'm gonna just copy the code or move the code from this front controller.
So this is view share Authuser.
So we need to import the auth class.
And I can't easily import the view class from core namespace because we have the name conflict in here.
So to import it I would need to use an alias which can be a core view.
This is what you do if you have the naming conflict.
And the first thing is the middleware needs to do something needs to be useful.
And this is what this middleware is doing.
But then we always need to remember to return the call to next middleware or the final route.
So this looks fine and we need to register this middleware.
I think we can do it inside this routes file.
Let's jump to it.
So in this file we've got the route definitions.
Let me now add the global middleware here as well.
So to the router we are calling Add global middleware which needs the class name to run.
We can use our view class name by importing the class.
And we are using the class constant.
Now this is registered and I think it should run.
So let me jump to our page and see if that's the case.
So we've got some issue.
We are calling an HTML.
That is strange, but I think there must be some issue inside the router implementation.
So we call the middleware and that's our implementation.
Let me take a look.
So we first store the final target which is the controller action.
Then we should go through every middleware and create a chain by creating a middleware, passing the
next thing to call to it.
And finally we start the chain by calling the last middleware that was registered.
So I see the problem here.
We are actually, or I am actually running those middlewares immediately.
Instead this should be a function.
It can be an arrow function because that is a one liner.
So I shouldn't be calling those middlewares immediately.
Instead, I should be creating those classes and wrapping everything in functions so that I can create
a chain of function calls like we see right here.
And I trigger this chain by starting the last element that was added, and then it works backwards so
that it calls the middleware middleware and finally the action.
This might be complicated.
There is a lot of abstraction here, but in reality this is quite simple.
Now I think it should work right now.
Let me refresh the page.
And indeed it works.
And we still get access to the user from the view, which means that the middleware has worked fine.
So to understand it better, I think we should be doing some logging.
So here, instead of using the arrow function, let me just add a full function and I'm gonna do error
logging.
That would let us see something in the terminal.
Okay.
So this needs to have this use statement now to use the middleware and to use whatever needs to be called
next.
Let me fix this keyword to be a function and before it runs whatever it needs to run, let's just do
a simple error log that will say we are okay, or maybe something different.
Middleware.
Running middleware.
Okay, so now we will be always seeing in the log in which order the middleware was run.
Let me add a semicolon in here.
And if I refresh this page we should already see something.
Okay so we've got that middleware.
We are running this middleware right here.
Now let's create some more middleware, shall we?
So we've got one global middleware that should be always run.
But we've got cases where middleware is not global like the authentication we don't always require.
Um what's this error here.
Um return value must be of type string null returned.
Um, okay.
I somehow returned.
Removed this return keyword.
Okay.
Let me go back to our topic.
So another middleware that we can create is authentication.
Let's jump to the command controller.
So instead of checking if the user is authenticated and then redirecting him, we can just make sure
that in this action it won't run if the user is not authenticated.
So for that we can create another middleware.
Let's call that the auth middleware.
So let's add a namespace here.
This is app Middlewares and the class is called auth.
It implements the middleware.
And let me quickly jump to this one and copy paste this method.
And now let me just move the logic from this controller.
So in this middleware I just want to check if the auth.
Okay.
So we need to import the auth class again.
This time we need to use an alias.
So this is our alias.
So if the user is well, Falsy is not authenticated.
Is null.
Then we do router unauthorized which would essentially break the chain.
It would redirect to 401 page.
Otherwise we just move to the next middleware and this needs to be registered.
But first this is a root middleware.
That's why in the router object I call add root middleware I call it off.
And only then I use the actual middleware class.
So this is first registering the possibility of adding this middleware to a route.
It's not registering the middleware to be run and for it to be run.
I added in this route definition.
So there is this fourth argument which accepts an array of middleware names where.
Now I can use this shortcut which is auth, which should now protect this route from running if someone
is not authenticated.
So in here I should be able to safely remove this code and instead when creating the command I would
just do auth.
User.
And at this point I am certain that the user object is there.
I can safely call it because I know that I have verified previously using middleware that this action
would never be called if the user is not authenticated, and we'd like to do the same with CSRF later
on, but this one would be global.
We want it always and you can see how simple this action can become if we just remove the code that
is often repeated.
We don't have the CSRF middleware yet, that's why I'm just going to leave it there.
But now let's see if this will work.
Let me jump to a post and see if middleware won't crash.
So I'm adding the comment.
It went fine to actually verify that I should make sure not this form.
It should be okay.
So that's the post form we just called show.
And the way I'm going to test that is I just want this form to be displayed at all times, even if I
sign out.
So I have signed out now and I go to This page, and I'd like the form to be always visible.
Let me remove this code like this.
And okay, now I see the form and when I submit something, I should just be directed to 401 page.
And this should happen in the middleware.
Let me add a comment.
Everything has worked fine and here we can see that the view middleware was run first, then the auth
middleware was run specifically for that route, which confirms that the middleware has redirected us
to 401, which is unauthorized.
So now let me bring back this code for displaying the form conditionally.
But anyway, I think you can see how this middleware works and how it has simplified the way we can
write those controllers.