Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 11 - Session returns null when we declare the middleware as a global middleware to run on every request

I was working on adding localization to my Laravel 11 project, and I created a middleware called SetLocale that consists of the codebase similar to below:

public function handle(Request $request, Closure $next): Response
    {
        App::setLocale(session()->get('locale'));
        return $next($request);
    }

I added it to my bootstrap/app.php file like this:

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__ . '/../routes/web.php',
        commands: __DIR__ . '/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->append(SetLocale::class);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

In my LocalizationController, I set the session like this:

public function setLocalization(string $locale): RedirectResponse
{
    session()->put('locale', $locale);
    App::setLocale($locale);
    return back();
}

My route in web.php looks like this:

Route::get('/locale/{locale}', [LocalizationController::class, 'setLocalization'])->name('locale.switch');

Here's what I tried:

  1. Used the Session facade throughout the codebase, but it didn't work.
  2. Used back()->with('locale', $locale); when returning in the setLocalization() function in the LocalizationController, but it didn't work.
  3. Tried various changes, but I couldn't retrieve the 'locale' session data in my middleware.

The only way I got it to work was by wrapping the middleware around the route like this:

Route::prefix('localization')->middleware([SetLocale::class])->group(function() {
   Route::get('/locale/{locale}', [LocalizationController::class, 'setLocalization'])->name('locale.switch');
});

Is my use of global middleware incorrect, or did Laravel change how it handles sessions for global middleware?

Just an FYI, Laravel has now moved its middleware to elsewhere. Now it's a clean file located in the bootstrap/app.php file.

Thanks for your help.

like image 936
Sreekesh Avatar asked Sep 07 '25 03:09

Sreekesh


1 Answers

To expand on the answer provided by @lagbox, the middleware that handles the session is defined as part of the web route middleware group. It is not defined as a global middleware. As mentioned by @lagbox, the route middleware are run after the global middleware.

The append() method you've used in your withMiddleware() callback will append the provided middleware to the global middleware. This is not what you want, since your new appended global middleware will run before the session middleware defined in the web route middleware group.

To get your desired result, you can use the appendToGroup() method instead of the append() method. This will append your middleware to the specified middleware group, instead of adding it as a global middleware.

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__ . '/../routes/web.php',
        commands: __DIR__ . '/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        // Use appendToGroup() to add the middleware to the 'web' group.
        $middleware->appendToGroup('web', SetLocale::class);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();
like image 154
patricus Avatar answered Sep 10 '25 04:09

patricus