1

I have seen some posts, like
Laravel5 - can't get Sessions working
Laravel 5 - session doesn't work

But I didn't get a solution for what I want.

I'm trying to build a multi language site. I use session to store this.
I know that in my controller, like ProductController, function index(){}, I can do like this

$this->request->session()->put('locale', 'en');
$this->request->session()->keep('locale');
$value = $this->request->session()->get('locale');
dd($value);
dd(Session::all());

Session::put('locale', 'en');
Session::keep('locale');
Session::save();
$value = $this->request->session()->get('locale');
dd($value);
dd(Session::all());

But I want to use in Controller.php, so I only need to do the session set and get only once, not in every controller I created.

<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Session;

class Controller extends BaseController
{
  use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

  public function __construct()
  {
    Session::put('locale', 'zh');
    Session::save('locale');
    $value = Session::get('locale');
    dd($value);
    dd(Session::all());
  }
}

But this doesn't work. Or I should do this in some place, some after middleware, I'm not familiar with this. Can someone give me some suggestions?

ronrun
  • 1,046
  • 2
  • 14
  • 33

2 Answers2

2

You can use a middleware and register it in your kernel.php file in the web index. It will be call for each web request.

So if you don't want to call it for each request, just add the middleware on concerned routes with Route::group for example and register it in kernel.php in $routeMiddleware.

Yebor974
  • 71
  • 3
0

I tried any solution I could find. Session doesn't work in middleware because the Session has not started yet. You'll always get null at this point.

There is a way and a catch. This how it works in my case for an ArticleController (L5.6)

public function __construct()
{
    $this->middleware(function ($request, $next)
    {
       $locale = config('app.fallback_locale');
        if (session('locale'))
        {
            $locale = session('locale');
        }
        if (\Request::has('lang')) 
        {
            $locale = \Request::get('lang');
            session(['locale' => $locale]);
        }
       \App::setLocale($locale);

       return $next($request);
    });
}

This does do the trick. BUT. Only after you run php artisan config:clear or config:cache. \Request::get('lang') uses ?lang=de in the route.

Keep in mind that the language stays German until ?lang=en comes by. This is useful for me because only parts of the page get translated. It is not SEO friendly.

The reason why this works and what I understood is the __construct in Controllers are cached. I'm not sure how that exactly works.

Check this working example where you see 'Artikel in Deutsch'. From there on you stay in German till you search in English or click on 'English Articles'

Dimitri Mostrey
  • 2,302
  • 1
  • 12
  • 11
  • Maybe you can try the After request middleware? The laravel official page about Middleware has Before request and After request. I'll try this part a week later. – ronrun Apr 10 '18 at 13:33
  • well, I tried that. Including running the config:clear. You can do it but you will have to but the sessions middleware higher on the execution ladder in the kernel. Not recommended if you don't want to break future upgrades. A lot of people complained about this after the L5.3. The understandable excuse was to speed up the execution time of a laravel project. So they build the controller constructs into the bootstrap folder. – Dimitri Mostrey Apr 10 '18 at 16:36
  • After middleware will miss the point of what you want to do. All is done, including building the html (blade) reply, ready to fire to the browser. There is not much you can do, except maybe: this user is online, put it in the db. – Dimitri Mostrey Apr 10 '18 at 16:40
  • Excused my 2 answers seem to contradict. After request middleware is not the same as afterMiddleware which does exist. In the words of the laravel site itself: "However, this middleware would perform its task after the request is handled by the application" – Dimitri Mostrey Apr 10 '18 at 16:44
  • It seems to all boils down to the order of middlewares in the kernel.php. Some have found a solution in changing the order, others have rejected the idea. We don't know what L5.* will bring. Using unanimous functions in the construct will probably keep on working. – Dimitri Mostrey Apr 10 '18 at 16:50