Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Tchopa's avatar

Middleware Troubles

Hey all,

Receiving this error

App\Http\Middleware\HasPermission::handle(): Argument #2 ($next) must be of type App\Http\Middleware\Closure, Closure given

This is my User Controller that is part of the problem I'm trying to solve.

use App\Http\Middleware\HasPermission;
    
class UserController extends Controller
{
 public function __construct() {
        $this->middleware(HasPermission::class, ['usermgmt.users','usermgmt.users.create','usermgmt.users.edit','users.delete'], ['only' => ['index','store']]);
        $this->middleware(HasPermission::class, ['usermgmt.users.create'], ['only' => ['create','store']]);
        $this->middleware(HasPermission::class, ['usermgmt.users.edit'], ['only' => ['edit','update']]);
        $this->middleware(HasPermission::class, ['users.delete'], ['only' => ['destroy']]); 
    }

And here is the HasPermission Middleware

namespace App\Http\Middleware;


class HasPermission
{

    public function handle($request, Closure $next,$permissions)
    {

        $permissions_array = explode('|', $permissions);
        foreach($permissions_array as $permission){
            if (!$request->user()->hasPermission($permission)){
                return redirect()->back();                        
            }
        }    
        return $next($request);
    }
}

I'm trying to make some custom middleware that will check the user's role before allowing them to access certain parts and permissions on the page.

Any help would be greatly appreciated, thanks!

0 likes
36 replies
Sinnbeck's avatar

Add this to the top of the middleware

use Closure;
1 like
Tchopa's avatar

@Sinnbeck

Thanks! That fixed the initial issue, now I'm getting this.

Too few arguments to function App\Http\Middleware\HasPermission::handle(), 2 passed in
Tchopa's avatar

@Sinnbeck

Is this not passing permissions to the middleware?

 $this->middleware(HasPermission::class, ['usermgmt.users','usermgmt.users.create','usermgmt.users.edit','users.delete'], ['only' => ['index','store']]);
Tchopa's avatar
   public function __construct() {
        $this->middleware(HasPermission::class, ['permission:usermgmt.users|usermgmt.users.create|usermgmt.users.edit|users.delete'], ['only' => ['index','store']]);
        $this->middleware(HasPermission::class, ['permission:usermgmt.users.create'], ['only' => ['create','store']]);
        $this->middleware(HasPermission::class, ['permission:usermgmt.users.edit'], ['only' => ['edit','update']]);
        $this->middleware(HasPermission::class, ['permission:users.delete'], ['only' => ['destroy']]); 
    }

I don't see how this isn't passing the correct parameters through

Sinnbeck's avatar

@Tchopa remove this HasPermission::class. Did you check the docs I linked?

Tchopa's avatar

@Sinnbeck That hasn't fixed my issue. Yes, I checked the docs you linked.

I have even tried to create a route middleware group but get the same error from before

Tchopa's avatar
Route::middleware('HasPermission')->group(function() {
Route::get('/usermgmt/users', [App\Http\Controllers\UserController::class, 'index'])->name('usermgmt.users');
Route::get('add-user', [App\Http\Controllers\UserController::class, 'create'])->name('usermgmt.users.create');
Route::delete('users/{user}',[App\Http\Controllers\UserController::class, 'destroy'])->name('users.destroy');
Route::get('users/{user}/edit', [App\Http\Controllers\UserController::class, 'edit'])->name('usermgmt.users.edit');
});

Middleware HasPermission has been declared in the Kernel.php as well. I believe it has to do with parameters, and I have checked the docs but am still not clear on where I am missing parameters

Sinnbeck's avatar

@Tchopa You are still not passing any parameters to it

middleware('HasPermission:manage-user')

Here I pass a parameter with the value "manage-user"

Tchopa's avatar

@Sinnbeck I have adjusted the controller to the below, and continue to receive the same error. usermgmt.users is a registered permission in the permissions table.

    public function __construct() {
        $this->middleware('HasPermission:usermgmt.users');
    }
Sinnbeck's avatar

@Tchopa So now you are using it in the controller instead of the route ? Show how you added it in routeMiddleware. And what exact error this time ?

Tchopa's avatar

@Sinnbeck I don't mind whether I use it in the route or the controller.

I've set it up on the route side for now. These are my routes

Route::middleware('HasPermission')->group(function() {
Route::get('/usermgmt/users', [App\Http\Controllers\UserController::class, 'index'])->name('usermgmt.users');
Route::get('add-user', [App\Http\Controllers\UserController::class, 'create'])->name('usermgmt.users.create');
Route::delete('users/{user}',[App\Http\Controllers\UserController::class, 'destroy'])->name('users.destroy');
Route::get('users/{user}/edit', [App\Http\Controllers\UserController::class, 'edit'])->name('usermgmt.users.edit');
});

This is how its been added in routeMiddleware

'HasPermission' => \App\Http\Middleware\HasPermission::class,
Tchopa's avatar

Here is the middleware HasPermission again

class HasPermission
{

    public function handle($request, Closure $next,$permissions)
    {

        $permissions_array = explode('|', $permissions);
        foreach($permissions_array as $permission){
            if (!$request->user()->hasPermission($permission)){
                return redirect()->back();                        
            }
        }    
        return $next($request);
    }
}

and here is the error

Too few arguments to function App\Http\Middleware\HasPermission::handle(), 2 passed in /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php on line 180 and exactly 3 expected
Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

@Tchopa Ok but pick one not both (for the same middleware) :)

Route::middleware('HasPermission:do-stuff')->group(function() { //still missing argument. Added it
Route::get('/usermgmt/users', [App\Http\Controllers\UserController::class, 'index'])->name('usermgmt.users');
Route::get('add-user', [App\Http\Controllers\UserController::class, 'create'])->name('usermgmt.users.create');
Route::delete('users/{user}',[App\Http\Controllers\UserController::class, 'destroy'])->name('users.destroy');
Route::get('users/{user}/edit', [App\Http\Controllers\UserController::class, 'edit'])->name('usermgmt.users.edit');
});
1 like
Tchopa's avatar

@Sinnbeck Oh I understand, insert the parameter next to the HasPermission, okay, can I use | to separate out multiple permissions ?

Sinnbeck's avatar

@Tchopa With a comma ,

From the docs

Multiple parameters should be delimited by commas:

Tchopa's avatar

@sinnbeck

I've done what you suggested, and I don't receive the error anymore. However the page doesn't work, it attempts to load but stops and then keeps me on the original page I was on. :/

I checked using php tinker to ensure the user has that permission, and it does

Sinnbeck's avatar

@Tchopa Then you are clearly hitting this

  return redirect()->back(); 

If the user does not have the first permission you redirect back. Maybe you wanted to check if they just have one of them ?

class HasPermission
{

    public function handle($request, Closure $next,$permissions)
    {

        $permissions_array = explode('|', $permissions);
        foreach($permissions_array as $permission){
            if ($request->user()->hasPermission($permission)){
                 return $next($request);
               
            }
        }    
        return redirect()->back(); 
    }
}
Sinnbeck's avatar

Or use dd() to check what happens inside the middleware

Tchopa's avatar

@Sinnbeck Yes, I believe it is the redirect that's sending me back.

I've tried dd() but it just stops the page from loading.

This page isn’t working

My roles and permissions all use a guard other than the default 'web' guard, is there something I need to declare in the controller/middleware to include that change? That could be why it's not detecting the permission, even though its there when I check through php tinker?

Sinnbeck's avatar

@Tchopa Does that guard have sessions ? Without sessions, no user :)

How are you using dd() ? can you show it? I cannot recreate the error

Tchopa's avatar

@Sinnbeck

I'm using the Auth0 guard so I do believe it has sessions, but not sure how to check that. Sorry

    public function handle($request, Closure $next,$permissions)
    {
        
        $permissions_array = explode('|', $permissions);
        foreach($permissions_array as $permission){
            if ($request->user()->hasPermissionTo($permission)){
                return $next($request);
            }
        }    
       dd();
       return redirect()->back();    
    }

}
Sinnbeck's avatar

@Tchopa You need to give it something you want to check

For example, here we dump both permissions and user to the screen to check both

dd($permissions, $request->user());
Tchopa's avatar

@Sinnbeck Understood, rookie error.

^ "usermgmt.users"

^ App\Models\User {#1473 ▼
  #primaryKey: "id"
  #fillable: array:5 [▼
    0 => "email"
    1 => "first_name"
    2 => "last_name"
    3 => "role"
    4 => "password"
  ]
  #hidden: array:2 [▼
    0 => "password"
    1 => "remember_token"
  ]
  #casts: array:1 [▼
    "email_verified_at" => "datetime"
  ]
  #guard_name: array:2 [▼
    0 => "auth0"
    1 => "web"
  ]
  #connection: null
  #table: null
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  +preventsLazyLoading: false
  #perPage: 15
  +exists: false
  +wasRecentlyCreated: false
  #escapeWhenCastingToString: false
  #attributes: array:1 [▼
    "email" => "[email protected]"
  ]
  #original: []
  #changes: []
  #classCastCache: []
  #attributeCastCache: []
  #dates: []
  #dateFormat: null
  #appends: []
  #dispatchesEvents: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  #visible: []
  #guarded: array:1 [▼
    0 => "*"
  ]
  #rememberTokenName: "remember_token"
Tchopa's avatar

@Sinnbeck

Hmm, comes back false.

^ false

Then something isn't working somewhere, weird

Seeing as the permissions and role are set to guard (auth0), I added auth0 with a comma after the permission parameter in the route middleware, still getting the same issue.

Sinnbeck's avatar

@Tchopa Go into the users hasPermissionTo() method and use dd() to debug that as well

Tchopa's avatar

@Sinnbeck Sorry I'm not quite sure I understand, what do you mean by users hasPermissionTo() method?

Sinnbeck's avatar

@Tchopa I assume you have a method named hasPermissionTo() as that isnt part of laravel. Or are you using a package?

Sinnbeck's avatar

@Tchopa Ok. Well Im am unsure how I can help further then. Maybe try clearning cache

Run this in tinker

app()->make(\Spatie\Permission\PermissionRegistrar::class)->forgetCachedPermissions();
Tchopa's avatar

@Sinnbeck Hmmm thats okay. I'll have a read through the Spatie docs and figure it out.

You've been a great help, and fixed most of the trouble I faced. Thank you!

Sinnbeck's avatar

@Tchopa Maybe try adding the guard name as second parameter

dd($request->user()->hasPermissionTo('usermgmt.users', 'auth0'));
Tchopa's avatar

@Sinnbeck

Hey! Yeah so I tried that dd and it came back with false again. I think it has to do with the guard method because the user has the permission, but the $request is showing it doesn't.

Please or to participate in this conversation.