ERaufi
ERaufi

Reputation: 1663

Add Multiple Middleware to Laravel Project

I'm new to laravel I have created middleware for my each role but when I add it to my route it won't work.

If I add single middleware to my route it works fine but when I add second and third one It will not work.

It won't shows the route to authorized user it redirect it to home,

My User Model:

public function IsAdmin()
{
    if($this->role_id =='1')
    {
        return true;
    }
    else
    {
        return false;
    }
}

public function IsManager()
{
    if($this->role_id =='2')
    {
        return true;
    }
    else
    {
        return false;
    }
}

public function IsUser()
{
    if($this->role_id =='3')
    {
        return true;
    }
    else
    {
        return false;
    }
}

My Kernal:

'IsAdmin' => \App\Http\Middleware\IsAdmin::class,
'IsManager' => \App\Http\Middleware\IsManager::class,
'IsUser' => \App\Http\Middleware\IsUser::class,

My IsAdmin Middlewares:

public function handle($request, Closure $next)
{
    $user =Auth::User();
    if(!$user->IsAdmin())
    {
        return redirect('stock');
    }
    return $next($request);
}

My IsManager

public function handle($request, Closure $next)
{
    $user =Auth::User();
    if(!$user->IsManager())
    {
        return redirect('stock');
    }
    return $next($request);
}

and IsUser

public function handle($request, Closure $next)
{
    $user =Auth::User();
    if(!$user->IsUser())
    {
        return redirect('stock');
    }
    return $next($request);
}

and finally my Route

Route::get('approv',['middleware'=>['IsManager','IsAdmin'],function(){
    return view('approv');
}]);

Upvotes: 3

Views: 1998

Answers (1)

apokryfos
apokryfos

Reputation: 40663

This will not work as you'd expect. All middleware need to pass in order for the request to be processed which means that your user will need to be both a manager and an admin at the same time which based on your setup is impossible.

You can get around this (kind of) by making a different kind of middleware:

Kernel:

'roles' => \App\Http\Middleware\Roles::class,

And the Roles middleware:

class Roles {

    private function checkRole($role) {
          switch ($role) {
              case 'user': return \Auth::user()->IsUser();
              case 'manager': return \Auth::user()->IsManager();
              case 'admin': return \Auth::user()->IsAdmin();
          }
          return false;
    }

    public function handle($request, Closure $next, ...$roles) 
    {
         foreach ($roles as $role) {
             if ($this->checkRole($role)) {
                 //At least one role passes
                 return $next($request);
             }
         } 
         //All checks failed so user does not have any of the required roles
         return redirect('stock');  
    }
}

Then to use this you simply do:

Route::get('approv',['middleware'=>['roles:manager,admin'],function(){
   return view('approv');
}]);

This works because Laravel Middleware support parameters. You can pass parameters as a comma separated list of strings where you declare the middleware. In this case this was done as roles:manager,admin

Laravel will then send these parameters as additional parameters in the handle method. These can be accessed using PHPs syntax for variadic arguments. In this particular case it's by using the array spread operator. This is documented as an example in the function arguments section of the PHP manual.

Note that this is actually equivalent to saying :

  public function handle($request, Closure $next, $role1=null, $role2=null, $role3=null)

but using the spread operator is much more convenient since ...$roles would be an array which contains only the roles that were passed in the middleware.

Upvotes: 3

Related Questions