Get url pattern in middleware's handle method in laravel - laravel

In routes.php I have defined route as
Route::get('entities/{id}/queries','QueryController#fetch');
and the actual example url is (for example): http://localhost:8000/entities/5/queries
public function handle($request, Closure $next, $guard = null) {
echo $request->path(); //returns entities/5/queries
return $next($request);
}
Now I need to access that url pattern in middleware.
i.e. entities/{id}/queries.
Is there any method that returns the url pattern?

You can do this by using the route inside your $request object.
Like this:
$request->route()->uri();
This will return entities/{id}/queries in your case.

Related

Laravel: Pass Model Binding to Route Middleware

I have routes that I'm grouping by Location. I need to authorize whether the current user can actually access a particular Location.
I'm wrapping routes in:
Route::group(['prefix' => "{location}", 'middleware' => "has-location-access:location"], function() {
...
My middleware handle method is as follows:
public function handle(Request $request, Closure $next, Location $location)
{
$account = Account::find($request->session()->get('account_id'));
$this->authorize('manageLocation', [$account, $location]);
return $next($request);
}
Instead of the model being passed into this method, I get a string of "location"
App\Http\Middleware\AuthorizeLocationAccess::handle(): Argument #3 ($location) must be of type App\Location, string given
How can I simply have it pass the Location $location into the handle method?
Try this:
Location::find($request->route()->location)

Laravel - change route in middleware

Let's say I have this kind of URLs :
example.com/en/
example.com/en/login
example.com/fr/login
I would like to use a middleware to set the language and then return the route to be handled without the language part. So the router would get / or /login, without any language stuff.
public function handle(Request $request, Closure $next) {
app()->setLocale($request->segment(1));
// $request->server->set('REQUEST_URI', substr($_SERVER['REQUEST_URI'], 4));// not working
return $next($request);
}
I would suggest to store the language in session and use a middleware to setLocale.
Working example
SetLocale.php middleware
public function handle($request, Closure $next)
{
if (Session::has('language'))
{
App::setLocale(strtolower(Session::get('language')));
}
return $next($request);
}
Controller function to set language to session
public function setLanguage(string $language)
{
if (Session::has('language'))
{
Session::forget('language');
}
Session::put('language', $language);
return redirect()->back();
}
So now on everything that happens on the website, the middleware will check the language and set it to what's in session.
Also don't forget to specify the middleware in $middlewareGroups in app\Http\Kernel.php
You can create a form anywhere on website for the user to choose his language preference with a route to the controller function.

Laravel Middleware changing header before passing to controller

I'm trying to change the header of my request before passing it to the controller using a middleware but it seems $next($request) executes the code in my controller. Is there a way to change the header then send the updated request to my controller?
My middleware:
class JWTAuthenticator
{
public function handle($request, Closure $next)
{
$token =JWTAuth::getToken();
$my_new_token = JWTAuth::refresh($token);
//it runs here
$response = $next($request);
//it runs this part after executing the controller
$response->header('Authorization','Bearer '.$my_new_token);
return $response;
}
This is how the middleware is assigned to my route:
Route::get('/{user}', 'v1\UserController#find')->middleware('jwt_auth');
That way you are excecuting the $response->header('Authorization','Bearer '.$my_new_token); sentence after the request was attended.
Change your code as follows:
class JWTAuthenticator
{
public function handle($request, Closure $next)
{
$token =JWTAuth::getToken();
$my_new_token = JWTAuth::refresh($token);
$request->headers->set('Authorization','Bearer '.$my_new_token);
return $next($request);
}

Is it possible and how do I if so to pass a variable parameter to a Middleware in Laravel

I looking to set up a Middleware to check if the user is a subscriber to the page that they are on. I have tried a couple of options but both has required passing the URL to the Middleware.
The Route
Route::get('premium/{id}', function ($id) {
return $id;
})->middleware('subscribe:{$id}');
The Middleware
public function handle($request, Closure $next, $subscribe)
{
//dd($subscribe);
$c = DB::table('suscribes')->where('user_id', $request->user()->id)->where('subscribed_to', $subscribe)->count();
return $next($request);
}
The above $subscribe obviously returns a string of {$id} but have tried concatenating. Is there a better way?
As I am using Cashier and Stripe I have also tried setting up a new plan for each user. From docs.
public function handle($request, Closure $next)
{
if ($request->user() && ! $request->user()->subscribed('main')) {
// This user is not a paying customer...
return redirect('billing');
}
return $next($request);
}
But I still need to pass the variable to 'main'.
I'm not sure if I understand your requirement completely. But to get the value of some Requests route Parameter you can use $request->route('param-identifyer') function. Passing {$id} as parameter to the middleware is the wrong approach.
public function handle($request, Closure $next, $subscribe)
{
dd($request->route('id'));
$c = DB::table('suscribes')->where('user_id', $request->user()->id)->where('subscribed_to', $subscribe)->count();
return $next($request);
}

get request params in middleware handle

I'm going through HTTP Middleware manual. And have created a middleware "LogAll" and added it to $middleware array in Kernel.php.
Everything works fine, except I don't have request params (post or get) in the handle method of LogAll
public function handle($request, Closure $next)
{
var_dump($request->all());
return $next($request);
}
it prints an empty array. When calling a url that matches this route:
Route::get('/{id}', ['as' => 'profile', function($id) {
return $id;
}]);
Note that, I have added a route pattern in boot method that checks id to be numeric.
For retrieving route parameters you should use route():
public function handle($request, Closure $next)
{
echo $request->route('id');
return $next($request);
}

Resources