I need to check a session variable to set a config item in laravel. I need this to run before the auth middleware though. I've tried all sorts of configurations to get it working but no matter what, auth runs before I set the database so it fails to find the user.
This is what I have so far:
Kernal.php
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\CheckTenant::class,
],
CheckTenant:
public function handle($request, Closure $next)
{
if(session()->has('database')){
//set db in config for eloquent
Config::set('database.connections.mysql.database', session('database'));
}
$response = $next($request);
return $response;
}
My route:
Route::group(['middleware' => 'auth'], function () {
// All my routes that needs a logged in user
Route::get('/dashboard', function () {
return view('jobs.index');
});
});
So basically I just need to set a config item at each request before it checks authentication.
Any help would be really appreciated.
The problem is you're trying to save data to config after the request is handled by the application (see Before & After Middleware section). Setting up config after request was handled by the app just doesn't make any sense.
Syntax should be:
public function handle($request, Closure $next)
{
if (session()->has('database')) {
Config::set('database.connections.mysql.database', session('database'));
}
$response = $next($request);
return $response;
}
Related
How do I solve my problem ?
Let me tell that how can i change language in laravel web page
List item
Route::get('/{lang?}', function($lang = null){
App::setLocale($lang);
return view('frontend.home');
});
This code will work only for the current request, so when you return the view, it's a new request.
So what you have to do is to persist the language, for each request, so we'll use middleware.
First of all, create a middleware, to check the which language is set, as follows,
public function handle(Request $request, Closure $next)
{
if (session()->has("lang")) {
App::setLocale(session()->get("lang"));
}
return $next($request);
}
What this code will do is, check if the session has the lang_code exists, so it will set it.
After that, you need to add this middleware to your $middlewareGroups, inside app\Http\Kernel.php, as follows :
<?php
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\Language::class, # This is the line we will add
],
Then finally we'll tweak a little bit your function to become like this :
Route::get('/{lang?}', function($lang = null){
App::setLocale($lang);
session()->put('lang', $lang);
return view('frontend.home');
});
Like this, within each request, the middleware will verify the language, and set it.
I'm writing localization with cookies. Localization works fine with cookies, but I want to set default language for someone who opened the website first time. So, I created a middleware for that and registered in route middlewares:
public function handle(Request $request, Closure $next)
{
get_cookie('lang') ?? set_cookie('lang', 'az');
return $next($request);
}
get_cookie and set_cookie comes from custom helpers:
if (!function_exists('get_cookie')) {
function get_cookie($name)
{
return Cookie::get($name);
}
}
if (!function_exists('set_cookie')) {
function set_cookie($name, $value)
{
return Cookie::queue($name, $value, time() * 360 * 60);
}
}
The issue is when I first opened website it sets cookie, but it isn't shows website with cookie. But, second time I opened website it shows the website with cookie.
I googled it and found this in stack overflow:
if($request->hasCookie('lang')) {
return $next($request);
}
$response = $next($request);
return $response->withCookie(cookie()->forever('lang', 'az'));
But it didn't work out for me, I think it works for old versions of laravel. I'm assuming that, I'm using middleware in the wrong way, but I didn't figured out. Any advice will be appreciated.
EDIT:
I changed middleware's place $routeMiddleware to $middlewareGroups. I think AddQueuedCookiesToResponse middleware has to be in that middleware list. But, it doesn't seem to be help. Maybe, there has to be another middleware in the list?
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\SetLanguage::class,
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
I didn't managed to find a way out to get it work with cookies. So, I just simply used sessions instead of cookies. So, in the middleware I set lang variable to session.
public function handle(Request $request, Closure $next)
{
if(!$request->session()->get('lang')) {
session(['lang' => 'az']);
}
return $next($request);
}
When the user logged in for the first time via email and password given to the user manually. They need to be forced to enter a new password (password and confirmed password - only two fields).
I have created a middleware:
class FirstTimeLogin
{
public function handle($request, Closure $next)
{
if ($request->user()->first_time_login) {
return redirect()->route('setup-password');
}
return $next($request);
}
}
In Kernel.php I have added \App\Http\Middleware\FirstTimeLogin::class in the $middlewareGroups array: eg:
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\FirstTimeLogin::class
]
];
web.php route look like this:
Route::group(['middleware' => ['auth']], function () {
Route::get('/home', 'HomeController#index')->name('home');
Route::get('/password/setup-password', 'Auth\SetupPasswordController#resetPasswordFirstTime')->name('setup-password');
Route::post('/password/setup-password', 'Auth\SetupPasswordController#updatePassword');
});
Problem is it keep redirecting many times on the browser, which caused ERR_TOO_MANY_REDIRECTS error on the browser. How to fix this?
You just applied the new middleware to all the web routes, so when user is redirected to ->route('setup-password') middleware kicks in again so you have infinite redirects
One way to fix this is to create an exclusion for those 2 routes that are used for password setup
Make sure you give second route a name, something like setup-password-post
And then change your middleware for code:
if ($request->user()->first_time_login) {
if (!in_array(Route::currentRouteName(), ['setup-password', 'setup-password-post'])) {
return redirect()->route('setup-password');
}
}
You'll need to put a check in to make sure the current route isn't setup-password.
Try changing your if statement to something like:
if ($request->user()->first_time_login && !$request->is('setup-password')) {
I'm starting to learn laravel 5.5 and I'm trying to create routes depending on the session
My code in web.php is:
if(session()->has("user")){
Route::any('/profile/view',"ProfileController#view");
}
if(session()->has("admin")){
Route::any('/game/new', "gameController#new");
}
but it donĀ“t works, it show me "page not found".
How i can do that?
RouteServiceProvider are booted before the StartSession middleware, so you cannot access session in route files. Use middleware to check instead.
Route::middleware('session.has.user')->group(function () {
Route::any('/profile/view',"ProfileController#view");
});
Route::middleware('session.has.admin')->group(function () {
Route::any('/game/new', "gameController#new");
});
To create middlewares:
php artisan make:middleware SessionHasUser
php artisan make:middleware SessionHasAdmin
Update middlewares to check the session, if it does not have corresponding session, abort the request:
app/Http/Middleware/SessionHasUser.php
public function handle($request, Closure $next)
{
if(session()->has("user")) {
return $next($request);
}
return abort(404);
}
Install Middlewares, so routing can use the middlewares
app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
...
'session.has.user' => , \App\Http\Middleware\SessionHasUser::class,
'session.has.admin' => \App\Http\Middleware\SessionHasAdmin::class,
...
],
This is my route:
Route::group(['middleware' => ['web']], function () {
Route::get('/xx', 'xx\yy#zz');
This is my modification in Kernel.php:
protected $middlewareGroups = [
'web' => [
\Keevitaja\Linguist\LocalizeUrls::class,
LocalizeUrls.php:
public function handle($request, Closure $next)
{
if ($this->linguist->hasDefaultSlug() && $this->linguist->isDefaultDenied()) {
abort(404);
}
if (Sentinel::check())
{
dd("logged in");
}
dd("NOT logged in");
I am using Sentinel and Linguist for authentication and localisation.
I would like to get 'system_language' from the User model: check if the user is logged in and if he is, I would like to get his preferred language from the DB and then pass it to Linguist:
$this->linguist->localize('fr');
Unfortunately, Sentinel:check() always returns FALSE in this middleware. In my own middleware it is working well.
For sure, I am using the right Facade of Sentinel, because $sentinel = Sentinel::findById(1); returns a valid result.
The problem was caused because of the order in the Kernel.php $middlewareGroups where \Keevitaja\Linguist\LocalizeUrls::class was on first position.