0
Php

Laravel – 5.0 And Middlewares

In Laravel-5.0 we can now use Middlewares instead of filters such as before but Middlewares are not new and was available in Laravel-4 as well. In version-4 if we need a Middleware then we may use a custom Middleware by creating a class and implementing the HttpKernelInterface interface, for example in laravel-4 we can create a class like following one as a custom Middleware:

app = $app;
    }

    
    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
    {
        // 1) Modify incoming request if needed and chain the app handler to get the response
        $response = $this->app->handle($request, $type, $catch);

        // 2) Modify the response if needed and return the response
        return $response;
    }
}

Then, from the app/start/global.php file we can register the Middleware using following code or we may create a Service Provider as well but not necessary:

App::middleware('Middleware\MyMiddleWare');

To unregister a Middlewares we can use something like this:

App::forgetMiddleware('Middleware\MyMiddleWare');

Actually a Middleware is one kind of filter and each one calls the Middleware that is right below it because Middlewares are constructed as a stack, which looks something like this:

private 'middlewares' => 
    array (size=6)
        0 => 
            object(Illuminate\Cookie\Guard)[93]
                protected 'app' => 
                    object(Illuminate\Cookie\Queue)[92]
                    ...
        1 =>
            object(Illuminate\Cookie\Queue)[92]
                protected 'app' => 
                    object(Illuminate\Session\Middleware)[91]
                    ...
        2 => 
            object(Illuminate\Session\Middleware)[91]
                protected 'app' => 
                    object(Illuminate\Http\FrameGuard)[89]
                        ...
        3 => 
            object(Illuminate\Http\FrameGuard)[89]
                protected 'app' => 
                    object(Middleware\MyMiddleWare)[90]
                    ...
        4 => 
            object(Middleware\MyMiddleWare)[90]
                protected 'app' => 
                    object(Illuminate\Foundation\Application)[2]
                    ...
       5 => 
           object(Illuminate\Foundation\Application)[2]
           ...

If you check the code in Illuminate\Foundation\Application.php file then you can see something like this:

public function run(SymfonyRequest $request = null)
{
    $request = $request ?: $this['request'];
    
    // Middlewares are called from here, start from the first one in the stack
    $response = with($stack = $this->getStackedClient())->handle($request);
		
    $response->send();

    $stack->terminate($request, $response);
}

Since each Middleware has a handle method and in the handle method of each one there is a call for the Middleware it’s below one using something like this:

$this->app->handle($request, $type, $catch);

So, the framework calls the handle on top but the top one gets executed at last, anyways, it was just a recap. So, what’s new in Laravel-5.0 with Middleware exactly?

Well, in Laravel-5.0 it replaces the filters, actually we can still use the filters but Middlewares are exclusively being used to replace old before filters such as auth, auth.basic, csrf etc and it’s a recommended way in laravel-5.0. In the Laracast Discussion Forum there is a comment by taylor Otwell as given below:

To clarify, filters are still available to use and assign to routes, because I don’t want to break people’s filter setups. However, going forward, we will be encouraging middlewares as they have a consistent signature across all types of requests.

So, let’s dig in to Laravel-5.0 Middleware now:

In Laravel-5.0 we have a new directory structure and in the app/Http folder there is a Middleware folder available which contains following files by default:

AuthMiddleware.php
BasicAuthMiddleware.php
CsrfMiddleware.php
GuestMiddleware.php
MaintenanceMiddleware.php

These are being used as Middlewars as a replacement of filters, for example we know that we can use a route before filter like:

$router->post(
    'user/register', [
    'uses' => 'UserController@register',
    'as' => 'user.add', 'before' => 'auth'
]);

This is not new and we know what it does, simply it just calls the auth filter before our register method gets called so we can check if the user is logged in or not, very simple and common task. It requires a route filter declaration as well but I’m just omitting this part here. So, instead of a before filter now a Middleware is being used and that Middleware class is available in the app/Http/Middleware directory; which is AuthMiddleware.php and it has the handle method to check whether the use is logged in or not. The code looks like this:

public function handle($request, Closure $next)
{
    if ($this->auth->guest())
    {
        if ($request->ajax())
        {
            return $this->response->make('Unauthorized', 401);
        }
        else
        {
            return $this->response->redirectGuest('auth/login');
        }
    }

    return $next($request);
}

Also in app/providers/AppServiceProviders.php file there is a protected $middleware property available which looks like this:

protected $middleware = [
    'auth' => 'App\Http\Middleware\AuthMiddleware',
    'auth.basic' => 'App\Http\Middleware\BasicAuthMiddleware',
    'csrf' => 'App\Http\Middleware\CsrfMiddleware',
    'guest' => 'App\Http\Middleware\GuestMiddleware',
];

This holds the Middlewares that are available to be used in our application but none of these are being called by default, it means that, if we don’t use them in out application then these won’t be called by the framework. Here, the array keys are aliases for each Middleware and we can use them, for example, if we want to use the auth for checking the he user is logged in or not then we may use it in our route like this:

$router->get('users', [
    'uses' => 'UserController@index',
    'as' => 'users.list', 'middleware' => 'auth'
]);

That’s it. Now, the handle method of AuthMiddleware class will be called on this route before it get’s dispatched. So, how can we create our own Middleware instead of a filter, for example, if we want to create a route filter for checking user permission on specific routes, in an ACL based application then in older version we could have used a route like this:

Route::get('user/register', array(
    'before' => 'auth',
    'uses' => 'UserController@index', 'as' => 'users.list'
));

In laravel-5.0 we can now use a Middleware instead and to create a Middleware we can use the artisan command line tool that Laravel provides and the command is as given below:

php artisan make:middleware PermissionMiddleware

This will create a class in app/Http/Middleware directory, something like this:


So, now we just need to write code in the handle method and finally we need to add this Middleware in the $middleware array in app/Providers/AppServiceProvider.php file, which may look like this after adding the entry:

protected $middleware = [
    'auth' => 'App\Http\Middleware\AuthMiddleware',
    'auth.basic' => 'App\Http\Middleware\BasicAuthMiddleware',
    'csrf' => 'App\Http\Middleware\CsrfMiddleware',
    'guest' => 'App\Http\Middleware\GuestMiddleware',
    'permission' => 'App\Http\Middleware\PermissionMiddleware',
];

That's it. Now let's write some code for the handle method as given below:

public function handle($request, Closure $next)
{
    if($this->hasPermission()) {
        return $next();
    }
	
    return redirect('/');
}

This is very simple, we are just checking if the user has permission using $this->hasPermission(), imagine that we have declared the hasPermission method in this class which does the checking and returns TRUE or FALSE and if our condition satisfies (User has the permission) then using $next() we are actually calling a closure and this is the another Middleware below it on the stack. So, it's important to call the $next() from each handle method in the Middleware class otherwise we won't get the expected result. So that's it. Now, we can use it in a route using something like this:

$router->get('users/register', [
    'uses' => 'UserController@index',
    'as' => 'users.list', 'middleware' => 'permission'
]);

Remember that, we can still use the before filter for this, check the documentation on Laravel website for details but this is more advanced and recommended way in Laravel-5.0.

Latest Blog

0
Php

PHP – 8.0 Match Expression

In PHP 8.0 there is a new feature or I should say a new language construct (keyword) going to be introduced,  which has been implemented depending […]