π Introduction Laravel provides a robust model route binding feature, making it easy to fetch models from route parameters. However, in a multi-tenant application, you might encounter a 404 error when using model binding due to middleware execution order. Recently, I faced this issue while working with Laravel 11 and discovered the importance of middleware […]
Laravel provides a robust model route binding feature, making it easy to fetch models from route parameters. However, in a multi-tenant application, you might encounter a 404 error when using model binding due to middleware execution order.
Recently, I faced this issue while working with Laravel 11 and discovered the importance of middleware priority. Hereβs how I solved it.
In my multi-tenant Laravel application, I use a single database connection and determine the tenant ID dynamically via middleware. The middleware sets the tenant ID in config()
from the session before queries execute.
However, when I used model route binding, I got a 404 error because:
SubstituteBindings::class
middleware was executing before my custom middleware.tenant_id
condition, returning no results and triggering a 404 page.Laravel 11 introduces the prependToPriorityList()
method, allowing us to prioritize middleware execution order.
First, create a middleware that sets the tenant ID from the session into config()
.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Session;
class SetTenant
{
public function handle($request, Closure $next)
{
$tenantId = Session::get('tenant_id');
Config::set('app.tenant_id', $tenantId);
return $next($request);
}
}
AppServiceProvider
To ensure SetTenant
runs before SubstituteBindings::class
, use:
use App\Http\Middleware\SetTenant;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
//
$middleware->prependToPriorityList(
\Illuminate\Routing\Middleware\SubstituteBindings::class,
SetTenant::class
);
$middleware->alias([
'set_tenant' => SetTenant::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
β
SetTenant::class
runs first, setting the tenant ID.
β
SubstituteBindings::class
runs after, ensuring model binding includes the tenant condition.
Using prependToPriorityList()
ensures that our middleware runs before Laravel binds models, fixing 404 errors in multi-tenant applications.
This small yet powerful adjustment can save you hours of debugging! Hope this helps fellow Laravel developers. π
Thanks for the reading! π