14

Im trying to work with Sessions in Laravel 5 Middleware, but they are not working. To be specific - var_dump(Session::all()); at the start of handle method gives me array with one value - _tokken, then at the end of this method

Session::put('lang',$locale);
var_dump(Session::all());

Gives me array with two values, _tokken and my lang key, but after refresh its the same, as I understand there should be same result after second refresh.

I though maybe I have my middleware loaded before Session middleware, which was true, then I switched and now my Kernel.php looks like this -

protected $middleware = [
        'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
        'Illuminate\Cookie\Middleware\EncryptCookies',
        'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
        'Illuminate\Session\Middleware\StartSession',
        'Illuminate\View\Middleware\ShareErrorsFromSession',
        'App\Http\Middleware\VerifyCsrfToken',
        'App\Http\Middleware\Language',

    ];

So I ask - what am I doing wrong?

Edit: Digging in Illuminate\Session\Middleware\StartSession I found this -

//Note that the Laravel sessions do not make use of PHP "native" sessions in any way since they are crappy.

as a comment, so my testing with session_status() is not relavent.

Subject
  • 215
  • 1
  • 2
  • 9

6 Answers6

15

I had the same problem, I was using Sessions to store the locale at login, then redirect to the main dashboard, but when the middleware loads, the session is not initiated yet. So it wouldn't work.

Let me say first, I'm no Laravel expert, but this way works in Laravel 5.3:

1) php artisan make:middleware SetApplicationLanguage

2) Add this to app/Http/Kernel.php $middlewareGroup variable:

\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\SetApplicationLanguage::class,

Notice that this new Middleware comes AFTER the StartSession class.

3) This is my app/Http/MiddleWare/SetApplicationLanguage.php:

namespace App\Http\Middleware;

use App;
use Closure;
use Illuminate\Support\Facades\Auth;

class SetApplicationLanguage
{

    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request $request            
     * @param \Closure $next            
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (isset(Auth::user()->locale)) {
            App::setLocale(Auth::user()->locale);
        }

        return $next($request);
    }
}

Notice that I don't use Session in it this example. That's because when I add my Middleware AFTER the StartSession class, session would work, but Auth::user() would be available again, so I could just use Auth::user()->locale and no need for Sessions at all.

But you could do it, just use App::setLocale(Session::get('locale')) instead and of cause include the Session facade.

WoodyDRN
  • 1,221
  • 20
  • 26
10

You need to use

\Session::save();

Whenever you want to save the modification so lets say I want to store the language of the user

\Session::put('lang','en');
\Session::save();

When you refresh now you will find your newly created key.

Islam Al-Rayan
  • 396
  • 2
  • 7
6

I had the same problem. @WoodyDRN said you need add StartSession middleware to your kernel file to you but it is not best way to solve this problem. So, how do I know that? Because I added and request the validation system is broken.

Best way to solve this problem, adding your language middleware to web middleware array

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \App\Http\Middleware\Localization::class,
    ],

    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];
Haydar ŞAHİN
  • 614
  • 1
  • 7
  • 12
  • So adding StartSession broke your app? Which version was this of Laravel? Cause it didn't break for me. – WoodyDRN May 05 '20 at 08:36
  • This worked. for me. I was attempting to set a variable for all views from a session variable. Adding the middleware to the web group makes total sense, I was first adding it to the global middleware array. Thanks! – Juan Rangel Aug 27 '20 at 20:53
  • @WoodyDRN Sorry for my late reply. I was very busy and I forget. This code snippet from Laravel 5.8. – Haydar ŞAHİN Sep 15 '20 at 14:47
4

If you need the session in your current middleware I found a(n) (ugly) workaround.

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Session\Middleware\StartSession;

class MiddlewareThatNeedsTheSession
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
     public function handle($request, Closure $next)
     {
        return app(StartSession::class)->handle($request, function ($request) use ($next) {

            /** @var Response $response */
            $response = $next($request);

            // do something with session
            session(['foo' => 'bar']);

            return $response;
        });
    }
}
online Thomas
  • 8,864
  • 6
  • 44
  • 85
  • 1
    It's worth pointing out that this example implements an "after" middleware - it runs after the request is handled by the app. That probably isn't what most who need the session in middleware would want. To change this, remove the `$response = $next($request);` line and chang the `return $response;` line to `return $next($request);` – BrynJ Feb 05 '19 at 11:20
  • This is for sure ugly logic because this will execute code and in some cases we do not need to execute code. – Muhammad Talha Jul 10 '21 at 07:12
1

Another thing to note, if you're making some middleware that's manipulating/retrieving data from the session, you need to make sure it's loaded after StartSession web middleware.

Daniel Dewhurst
  • 2,533
  • 2
  • 21
  • 39
0

I had same problem, I was setting value in Middleware and unsetting in same place if some condition is true.

I totally forgot about 404s, some files was getting 404 (missing images) so nginx was passing request to Laravel app to show 404 page, and because it was other url I was unsetting there. I think its the same issue with storing language stuff in session. Just check your browser networking and see what requests are being made while loading the page, you might be setting and unsetting at the same time

midan888
  • 179
  • 6