5

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.

3
  • 1
    You posted this yesterday, I see now that the post is deleted, do not do that, don't delete a post and repost if it does not get expected attention... Commented May 6, 2024 at 10:44
  • I think you have mistook my post for someone else's. This is my first time posting on stack overflow. Commented May 6, 2024 at 16:01
  • You may be totally right, ignore my comment in that case. Someone posted exactly the same issue Commented May 6, 2024 at 16:37

2 Answers 2

19

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();
Sign up to request clarification or add additional context in comments.

6 Comments

Yep, that worked! So appendToGroup() means the same as wrapping our entire web.php routes with our SetLocale() middleware. Thank you!
You can also do the following instead of appendToGroup() incase anyone else sees this in the future: $middleware->web(append: [ SetLocale::class ]);
I have the same problem but to me it doesn't work: if I add the middleware to web group it somehow happen after render so the setLocale has no effect. Instead adding the middleware as global effectively change the locale, but not having access to session or auth i cannot get the correct value. Someone can help me? I'm using laravel 11 and filament 3.2
@TizianoMischi I believe you'll need to ask a new question and provide the details relevant to your issue. It sounds like you're middleware is setup as an after middleware, but without the proper details, we can't help.
@patricus thanks, I've solved, it's filament that doesn't use bootstrap middleware but its own and you have to register the middleware there
|
3

Global middleware run before route middleware. The middleware that starts the session is a route middleware; there is no session when the global middleware run. Add your middleware as a route middleware to the entire group of routes you want just like the web group is applied to all web routes or add this middleware to the web group.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.