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

Ligonsker's avatar

Nested Middleware - make the inside Middleware an exception

Not sure if it's possible.

But let's say I have a big group of routes that all uses some middleware with specific value:

Route::middleware(['permission:permission_x'])->group(function () {
    // many routes
}

But some routes inside are also allowed another permission:

Route::middleware(['permission:permission_x'])->group(function () {
    // many routes
    Route::middleware(['permission:permission_y'])->group(function () {
       // some specific route
    });
});

Is it possible to do it somehow? Or not because it first goes through the first Middleware, then blocks whoever is not in the parent permission? Because if not it means I have to divide it to many other groups

0 likes
18 replies
Ligonsker's avatar

@MichalOravec I really read the docs but sometimes miss stuffπŸ€ͺ

But, will it work in such case of Middleware with parameters (I will test it now but still wanted to ask you):

Route::middleware(['permission:permission_x'])->group(function () {
    // many routes
    Route::middleware(['permission:permission_x,permission_y'])->group(function () {
       // some specific route
    })->withoutMiddleware(['permission:permission_x']);
});

Because it's not that I want to exclude the Middleware entirely, just change the parameters. I don't want it to even ignore itself

Sinnbeck's avatar

Routes middleware goes from the outside and in. So it checks the othermost first, and then the inner. So //many routes only require permission:permission_x, while //some specific routes require both permission:permission_x and permission:permission_y

1 like
Ligonsker's avatar

@Sinnbeck Yep, this is what's I'm going to do because anyway @michaloravec this is Laravel 6 (I know it's not supported but it takes time to approve the updates where I work), and it tells me that withoutMiddleware() does not exist.

@sinnbeck if I was working on Laravel 9, would the withoutMiddleware still work? Even though it's from outside in?

Ligonsker's avatar

@Sinnbeck Would that work? Even though normally it goes outside in? And in this specific case, it's the same Middleware (different parameters):

Route::middleware(['permission:permission_x'])->group(function () {
    // many routes
    Route::middleware(['permission:permission_x,permission_y'])->group(function () {
       // some specific route
    })->withoutMiddleware(['permission:permission_x']);
});
Sinnbeck's avatar

@Ligonsker Why would you nest it in the outer middleware in the first place? I havent tested so myself, as I would refrain from using this pattern, but I would assume so (no promises)

1 like
Ligonsker's avatar

@Sinnbeck Because in the real file there are many routes that use permission_x, and only a few use also permission_y (Updated the previous comment, added both):

Route::middleware(['permission:permission_x'])->group(function () {

    // many routes

    Route::middleware(['permission:permission_x,permission_y'])->group(function () {
           // some specific route
    })->withoutMiddleware(['permission:permission_x']);
});

And since there is only a small group of routes that needs both, I can wrap everything with the permission that is used the most with exception of a few, so not to repeat many times. (Because permission group x does not necessarily include the same users in permission group y)

Snapey's avatar

@Ligonsker Perhaps you need to look a bit broader than that.

Ideally permission would control the ability to do one thing, whereas a user might have a role that conveys a number of permissions.

So nesting permissions never becomes a problem.

1 like
Ligonsker's avatar

@Snapey you are correct, in fact I was wrong in my example, in reality it's more like "permission groups". But in my case there is still this case where sometimes 2 separate roles, for example 2 types of managers have similar permissions, but not identical, but for that specific route I want both of the managers to be able to use it.

I know it is still likely due to the design and broader problem - what could I do to make it better? Or in this case it's alright

Sinnbeck's avatar

@Ligonsker I cannot think of a reason why 1 action can be done with two different permissions? I would assume there is just one permission and that both manager roles has this

1 like
Ligonsker's avatar

@Sinnbeck You are right, then I should probably change the design as well. Currently how it works is that there is a table of permission_groups, which is simply column of user_id and the permission_name:

user_id | permission_name

so it implicitly creates "permission groups", but it's not exactly. So a permission group is all the users that are assigned the same permission_name (which also turns out to be the group name).

Should I change this design? Maybe add another table? And create a relationship between the role and the permission?

So I will have this table:

permission_name | permission_group

and then the user will have relationship between the actual group:

user_id | permission_group

Would you do it like that? Or something else?

Ligonsker's avatar

@Sinnbeck I used spatie in a previous project (not in the current place I Work), but if you remember, installing a new package here . . .πŸ˜…πŸ˜…πŸ˜…

But looks like Spatie also creates these tables: permissions and groups, unlike my current situation where it's only list of users-to-permission relationship

Sinnbeck's avatar

@Ligonsker ah yes I forgot. But you could perhaps just copy the files over? It's a few traits, models and migrations and such. Just change the namespace

1 like
Ligonsker's avatar

@Sinnbeck I could try, but that also means to completely remove the permission check in the web.php file right? completely change the design

Please or to participate in this conversation.