Make a variable available in all controllers - php

I am not sure the title of the question is clear, so I will try to explain it in details.
I want to execute a piece of code in every controller automatically, assign the result to a variable that will be globally accessible everywhere.
So the code that need to be run will be like this:
function getLanguage() {
session('lang') ? session('lang') : 'en';
}
$LANG = getLanguage();
In any controller I need to access that variable like this:
myModel::all($LANG);
Also in the view, it would be helpful to access that variable as well (if possible)
<div> User language: {{$LANG}}</div>
Is there any place where I can execute that piece of code automatically?

Create a middleware
Add new middleware to App\Http\Kernels $middleware property, if you want it to run on every request. You may also put into $middlewareGroups property's web key.
Your middleware's handle method will be like this
public function handle(Request $request, Closure $next)
{
Config::set('some-name.some-sub-name', session('lang') ?: 'en');
return $next($request);
}
You will be updating a config in your middleware. This config has to be set only in this middleware to prevent possible problems of shared global state. (it is also important to be unique)
Then you can use it with config('some-name.some-sub-name')

In your use-case, you should implement a global middleware which sets the locale as you wish
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Session\SessionManager;
use Illuminate\Contracts\Foundation\Application;
class CheckLocale
{
/**
* The application instance.
*
* #var \Illuminate\Contracts\Foundation\Application
*/
protected $app;
/**
* The session manager instance.
*
* #var \Illuminate\Session\SessionManager
*/
protected $sessionManager;
public function __construct(Application $app, SessionManager $sessionManager)
{
$this->app = $app;
$this->sessionManager = $sessionManager;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
$this->app->setLocale($this->sessionManager->get('lang', 'en'));
return $next($request);
}
}
After setting it as a global middleware, you can access it wherever you need it from a controller or view
Controller
public function foo(Application $app)
{
$lang = $app->getLocale();
}
In a Blade view
#inject('app', Illuminate\Contracts\Foundation\Application::class)
{{ $app->getLocale() }}
For any other variable, you may directly use Laravel container
In a service provider register method:
$this->app->singleton('lang', function ($app) {
return $app['session']->get('lang', 'en');
});
And wherever else
app('lang');

Related

Where is "Closure" class located inside Lumen Framework?

Many of the processes inside lumen use the "closure" class. I know what a closure is, but still I'd like to know what it looks like in Lumen. Therefore, I need to find the file where the class is defined.
For example, my authenticate.php middleware uses "Closure", you can see it in the top of the code:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Factory as Auth;
class Authenticate
{
/**
* The authentication guard factory instance.
*
* #var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* #param \Illuminate\Contracts\Auth\Factory $auth
* #return void
*/
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if ($this->auth->guard($guard)->guest()) {
return response('Unauthorized.', 401);
}
return $next($request);
}
}
But unlike any other class in Lumen, this one doesn't provide any path to the location of the class in the source code. I've looked up the root directory, and it's not there.
So where is it?
You can scan in the documentation in PHP Closure Class. It was added in PHP 5.3 it is built in PHP not under Lumen Framework or Laravel.

Set Global Variable accessible in all controller methods Laravel 5.3

I have this route
Route::group(['middleware' => 'returnphase'], function () {
Route::get('/', 'FrontendController#home')->name('homepage');
});
My middleware check in what Phase (logic is non important now) is my application, i need that the controller setting up a global variable that i can use in all methods inside FrontendController because i need to read from database some data that depend from that check:
Middleware code, i need to set a phase_id varibale that i can use in may frontend controller.
namespace Cbcc\Http\Middleware;
use Closure;
class ReturnPhaseMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
/**
* TODO: Phase id check logic
*/
// SETTING GLOBAL PHASE ID VARIABLE (EXAMPLE PHASE_ID = 1)
return $next($request);
}
}
My frontend controller
//FrontEndController
namespace Cbcc\Http\Controllers;
use Cbcc\Page;
use Illuminate\Http\Request;
class FrontendController extends Controller
{
public function home()
{
$page = Page::where([
['phase_id',/**** I NEED GLOBAL PHASE ID HERE SETTING BY MIDDLEWARE***/],
['type','home']
])->get()[0];
return view('frontend.index',compact('page'));
}
}
Any ideas to do that?
You might want to user Session variables. What about using flash session variables since it seems you only use this variable once :
Middleware
class ReturnPhaseMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
/**
* TODO: Phase id check logic
*/
$request->session()->flash('PHASE_ID', '1');
return $next($request);
}
}
Front-end controller
class FrontendController extends Controller
{
public function home(Request $request)
{
$page = Page::where([
['phase_id', $request->session()->get('PHASE_Id')],
['type','home']
])->get()[0];
return view('frontend.index',compact('page'));
}
}
The special property of flash session variables is that they get destroyed at the next request.
Reference : https://laravel.com/docs/5.4/session#flash-data
Good strategy, and without using session?
What do you think about my solution?
// Frontend Controlller
namespace Cbcc\Http\Controllers;
use Cbcc\Lib\CheckPhaseInterface;
use Cbcc\Page;
class FrontendController extends Controller
{
protected
$phase_id;
public function __construct()
{
$this->middleware(function ($request, $next) {
// this 2 lines return phase id logic, for example $check->run() return 1 (int)
$check = resolve(CheckPhaseInterface::class);
$this->phase_id = $check->run();
return $next($request);
});
}
public function home()
{
$page = $this->getPageContent();
return view('frontend.index',compact('page'));
}
protected function getPageContent()
{
return Page::where([
['phase_id',$this->phase_id],
['type','home']
])->get()[0];
}
}

passing data from middleware to view or alternative way to show specific data in every page

in my website i have a fairly complected category which i have to show in every view (in the client side) so i thought i put the code for creating category in a middleware and pass the result to views
so i've created my middleware but i cant figure out how can i pass its data to my view withouth having to do something in the controllers
i've tried these methods in my middleware
<?php
namespace App\Http\Middleware;
use Closure;
class CtegoryMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$request->merge(array("all_categories" => "abc"));
$request['all_categories']= 'abc';
return $next($request);
}
}
route :
Route::group(['middleware' => ['category' ]], function () {
Route::get('/', 'HomeController#index');
});
but in my view when i echo all_categories i get
Undefined variable: all_categories
btw i've checked by echoing something , the middleware gets triggered on the request
I think in your use case, using a globally available view variable should suffice.
<?php
namespace App\Http\Middleware;
use Closure;
class CtegoryMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$request->merge(array("all_categories" => "abc"));
$request['all_categories']= 'abc';
/**
* This variable is available globally on all your views, and sub-views
*/
view()->share('global_all_categories', 'abc');
return $next($request);
}
}
The variable is loaded once (if you do database query, the query will only execute once), and the variable is then stored in the View factory.

Error adding IP whitelist to Laravel 5 maintenance mode

I'm configuring maintenance mode in Laravel. I'm trying to add in an IP whitelist.
When I run this code:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckForMaintenanceMode
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->app->isDownForMaintenance() &&
!in_array($request->getClientIP(), ['127.0.0.1']))
{
return response('Be right back!', 503);
}
return $next($request);
}
}
I get this error:
Undefined property: App\Http\Middleware\CheckForMaintenanceMode::$app
Can someone tell me what's the problem is?
Update
As of Laravel 5.6.21, this functionality is now built into Laravel. The php artisan down command now takes --allow parameters which lets you specify the IP addresses to allow to access the site.
So, instead of making any customizations, you'd just need to run php artisan down --allow=127.0.0.1.
Original
You're using $this->app, but your class doesn't have an $app property. You can either just use the app() helper method, you can inject the Application into your middleware, or you can extend Laravel's CheckForMaintenanceMode class, which will take care of all that for you.
Extend Laravel:
class CheckForMaintenanceMode extends \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode
Dependency Injection:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Foundation\Application;
class CheckForMaintenanceMode
{
/**
* The application implementation.
*
* #var \Illuminate\Contracts\Foundation\Application
*/
protected $app;
/**
* Create a new middleware instance.
*
* #param \Illuminate\Contracts\Foundation\Application $app
* #return void
*/
public function __construct(Application $app)
{
$this->app = $app;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->app->isDownForMaintenance() &&
!in_array($request->getClientIP(), ['127.0.0.1']))
{
return response('Be right back!', 503);
}
return $next($request);
}
}
app() Helper
public function handle($request, Closure $next)
{
if (app()->isDownForMaintenance() &&
!in_array($request->getClientIP(), ['127.0.0.1']))
{
return response('Be right back!', 503);
}
return $next($request);
}

How can I use laravel 5.1 middleware parameter for multiple auth and protected routes?

I'm new to laravel 5.1.
How can I use middleware parameter to protect my admin routes from users ?
something like this:
Route::group(['middleware' => 'auth:admin'], function()
/* Admin only Routes*/
{
//////
});
I have a field "role" in my "users" table that get two values:
1 for admin
2 for users
In my application, users, have their protected route.
I don't want to use packages.
You can do something like this. Inject the Guard class, then use it to check the user. You dont need to pass the parameter really. Just name your middleware 'admin' or something. The following middleware will check if the current user's role is admin, and if not, redirect to another route. You can do whatever you prefer on failure.
<?php
namespace Portal\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Admin
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if($this->auth->user()->role != 'admin') {
return redirect()->route('not-an-admin');
}
return $next($request);
}
}
In case you do want to pass the parameter, you can do this:
public function handle($request, Closure $next, $role)
{
if($this->auth->user()->role != $role) {
return redirect()->route('roles-dont-match');
}
return $next($request);
}

Categories