Laravel - Send data from middleware to route - php

I am trying to send some data from the handle function in a middleware:
<?php
namespace App\Http\Middleware;
class LanguageSwitcher
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (!Session::has('locale'))
{
Session::put('locale',Config::get('app.locale'));
}
App::setLocale(session('locale'));
$locale = session('locale'); // => The data I want to send
return $next($request);
}
}
My web.php:
Route::group(['middleware'=>'language'], function () {
// I want to set the prefix to locale here, but it's undefined
Route::group(['prefix' => $locale], function () {
});
});
I have tried to get the $locale in web.php using Session::get('locale') but I get Null.
So, is there any way to send it from the middleware to the route?

i guest you want to use locale for support multi language. You can do with set locale in middleware and use the locale in your route. Here is my example https://pastebin.pl/view/c5034cb9

Related

Getting a redirect loop when using Middleware

In my Laravel application I use the auth Middleware to ensure only authenticated users can reach particular routes.
So, in my routes/web.php I have something like this:
Route::group(['middleware' => ['auth', 'user.required.fields']], function () {
}
As you can see I've added an extra Middleware: user.required.fields it looks like this
<?php
namespace App\Http\Middleware;
use Closure;
class CheckUserRequiredFields
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(auth()->user()->has_filled_required_fields){
return $next($request);
}
else{
return redirect()->route('new-user');
}
}
}
The attribute in question looks like this:
/**
* If the user has filled in their role, department and location, allow full access to the intranet
*
* #return void
*/
public function getHasFilledRequiredFieldsAttribute()
{
if ($this->role && $this->department && $this->location) {
return true;
} else {
return false;
}
}
However, this causes an infinite loop.
Is there something in the auth middleware that would cause this? It's almost like the middleware calls itself over and over.
The code will correctly redirect to route('new-user)` but then repeatedly hits the route.
I think you have your route('new-user') defined within this group:
Route::group(['middleware' => ['auth', 'user.required.fields']], function () {
//
}
So, it will be checked by the middleware, that returns the same route again and again, which cause the mentioned loop.
A possible solution is to remove the route from this grop and also not protect it with the CheckUserRequiredFields middleware.

Laravel 5: Access custom route property

Is there a way to access a custom route parameter, same way as route "name": 'cache'=>true
Route::GET('tools/languages/{page?}', array('uses'=> 'Tools#list_languages', 'as'=>'list_languages', 'cache'=>true));
How to access cache value from Controller?
thanks,
Yes you can get your Route parameter from Middleware.
In your middleware you can get "matched route object" like this :
class MyMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$matchedRouteObject = $request->route();
$next($request);
}
}
See print_r($request->route()) there is a property that named action in this Route object. action property has all parameters of matched Route.
routes/web.php :
Route::get('tools/languages/{page?}', [
'uses' => 'Tools#list_languages',
'middleware' => 'App\Http\Middleware\MyMiddleware',
'cache' => 'value'
]);
app/Http/Middleware/MyMiddleware.php :
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Response;
class MyMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$matchedRouteObject = $this->route();
$deedVariable = $mathedRouteObject->action['cache']; // here you got your variable.
return $next($request);
}
}
Extending #Exprator answer, you could access the parameter in your controller as
public function list_languages(Request $request)
{
$request->route()->getAction()['cache']; // returns true
}
https://laravel.com/api/5.4/Illuminate/Routing/Route.html#method_getAction

Laravel Routing - Subdomain filtering

I'm using Laravel 5.4 and I'd like to filter the subdomain.
web.php
Route::group(['domain' => '{city}.localhost'], function () {
if ($city does not exist in database) {rediret to localhost};
Route::get('/', 'HomeController#home');
});
What I'd like
If subdomain exists in the database continue. Otherwise redirect to the same address but without a subdomain.
I would suggest using middleware to interrogate the $request URL and redirect accordingly, much like the RedirectIfAuthenticated middleware does.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CheckSubdomain
{
/**
* 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)
{
// check $request->url() here...
if ($notInDatabase) {
return redirect()->route('/somewhere');
}
return $next($request);
}
}

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.

Laravel 5.1 ACL

I've read about the new policy features in Laravel 5.1.
It looks from the docs that a blacklist approach is chosen by default. E.g. a controller actions is possible until access is checked and denied using a policy.
Is it possible to turn this into a whitelist approach? Thus, every controller action is denied except when it's explicitly granted.
I just found a rather clean way I think, in your routes, you pass a middleware and the policy that needs to be checked.
Example code:
<?php
namespace App\Http\Middleware;
use Closure;
class PolicyMiddleware
{
/**
* Run the request filter.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string $policy The policy that will be checked
* #return mixed
*/
public function handle($request, Closure $next, $policy)
{
if (! $request->user()->can($policy)) {
// Redirect...
}
return $next($request);
}
}
And the corresponding route:
Route::put('post/{id}', ['middleware' => 'policy:policytobechecked', function ($id) {
//
}]);

Categories