How to retrieve a url parameter from request in Laravel 5? - php

I want to perform certain operations with a model in a middleware. Here is an example of what I want to achieve:
public function handle($request, Closure $next)
{
$itemId = $request->param('item'); // <-- invalid code, serves for illustration purposes only
$item = Item::find($itemId);
if($item->isBad()) return redirect(route('dont_worry'));
return $next($request);
}
My question is, how can I retrieve the desired parameter from the $request?

public function handle(Request $request, Closure $next)
{
$itemId = $request->item;
//..............
}

If the parameter is part of a URL and this code is being used in Middleware, you can access the parameter by it's name from the route given:
public function handle($request, Closure $next)
{
$itemId = $request->route()->getParameter('item');
$item = Item::find($itemId);
if($item->isBad()) return redirect(route('dont_worry'));
return $next($request);
}
This is based on having a route like: '/getItem/{item}'

Use this after Laravel 5.5
public function handle($request, Closure $next)
{
$item = Item::find($request->route()->parameter('item'));
if($item->isBad()) return redirect(route('dont_worry'));
return $next($request);
}

Related

How to remove query parameter from url in laravel via middleware?

I am using laravel and I am facing one problem, I have URL like this
https://example.com?version=2.2.0
Now I am creating middleware after matching the version the query parameter should remove.
Below is the middleware code
public function handle($request, Closure $next)
{
$input = $request->all();
$request->replace($request->except(['version']));
return $next($request);
}
But it is not working to remove query parameters although working post data.
Why don't use just remove method?
public function handle($request, Closure $next)
{
$input = $request->all();
$request->remove('version');
return $next($request);
}
This is what remove method does under the hood, in laravel source code:
/**
* Removes a parameter.
*/
public function remove(string $key)
{
unset($this->parameters[$key]);
}
Just unset the query param.
public function handle($request, Closure $next)
{
if( $request->has('version') ){
unset($request['version']);
}
return $next($request);
}
If i understand correctly you want to remove the ?version=2.2.0 from your url?
You can do this by using this code:
// This only works for GET requests, NOT for POST requests.
if ($request->has('version')) {
return redirect()->to($request->fullUrlWithoutQuery('version'));
}
return $next($request);

Add Multiple Middleware to Laravel Project

I'm new to laravel I have created middleware for my each role but when I add it to my route it won't work.
If I add single middleware to my route it works fine but when I add second and third one It will not work.
It won't shows the route to authorized user it redirect it to home,
My User Model:
public function IsAdmin()
{
if($this->role_id =='1')
{
return true;
}
else
{
return false;
}
}
public function IsManager()
{
if($this->role_id =='2')
{
return true;
}
else
{
return false;
}
}
public function IsUser()
{
if($this->role_id =='3')
{
return true;
}
else
{
return false;
}
}
My Kernal:
'IsAdmin' => \App\Http\Middleware\IsAdmin::class,
'IsManager' => \App\Http\Middleware\IsManager::class,
'IsUser' => \App\Http\Middleware\IsUser::class,
My IsAdmin Middlewares:
public function handle($request, Closure $next)
{
$user =Auth::User();
if(!$user->IsAdmin())
{
return redirect('stock');
}
return $next($request);
}
My IsManager
public function handle($request, Closure $next)
{
$user =Auth::User();
if(!$user->IsManager())
{
return redirect('stock');
}
return $next($request);
}
and IsUser
public function handle($request, Closure $next)
{
$user =Auth::User();
if(!$user->IsUser())
{
return redirect('stock');
}
return $next($request);
}
and finally my Route
Route::get('approv',['middleware'=>['IsManager','IsAdmin'],function(){
return view('approv');
}]);
This will not work as you'd expect. All middleware need to pass in order for the request to be processed which means that your user will need to be both a manager and an admin at the same time which based on your setup is impossible.
You can get around this (kind of) by making a different kind of middleware:
Kernel:
'roles' => \App\Http\Middleware\Roles::class,
And the Roles middleware:
class Roles {
private function checkRole($role) {
switch ($role) {
case 'user': return \Auth::user()->IsUser();
case 'manager': return \Auth::user()->IsManager();
case 'admin': return \Auth::user()->IsAdmin();
}
return false;
}
public function handle($request, Closure $next, ...$roles)
{
foreach ($roles as $role) {
if ($this->checkRole($role)) {
//At least one role passes
return $next($request);
}
}
//All checks failed so user does not have any of the required roles
return redirect('stock');
}
}
Then to use this you simply do:
Route::get('approv',['middleware'=>['roles:manager,admin'],function(){
return view('approv');
}]);
This works because Laravel Middleware support parameters. You can pass parameters as a comma separated list of strings where you declare the middleware. In this case this was done as roles:manager,admin
Laravel will then send these parameters as additional parameters in the handle method. These can be accessed using PHPs syntax for variadic arguments. In this particular case it's by using the array spread operator. This is documented as an example in the function arguments section of the PHP manual.
Note that this is actually equivalent to saying :
public function handle($request, Closure $next, $role1=null, $role2=null, $role3=null)
but using the spread operator is much more convenient since ...$roles would be an array which contains only the roles that were passed in the middleware.

Display request method (GET,POST, ..) in Laravel middleware

I have a middleware class in Laravel and I wanted to get the action name like (GET, POST, DELETE, PUT,...) for logging the information. I have below code:
public function handle($request, Closure $next)
{
$api_key = $request->headers->get('x-api-key');
if($api_key!=$this->auth_key){
return $this->response->unauthorize(
"You're not authorize to access. Make sure that you're passing your api Key"
);
}
return $next($request);
}
I have this line $request->route(); that may help but I don't know about the method.
use Illuminate\Routing\Route;
private $route;
public __construct(Route $route) {
$this->route = $route;
}
public function handle($request, Closure $next)
{
$action = $this->route->getMethods(); // return array
$api_key = $request->headers->get('x-api-key');
if($api_key!=$this->auth_key){
return $this->response->unauthorize(
"You're not authorize to access. Make sure that you're passing your api Key"
);
}
return $next($request);
}

Pass an array to a middleware in laravel

I got this handle in a middleware called rolMiddleware:
public function handle($request, Closure $next, $roles)
{
//dd($request->user());
foreach ($roles as $rol) {
if ($request->user()->getTipoUsuario($request->user()->tipo_usuario_id)->getNombreTipoUsuario() == $rol) {
return $next($request);
}
}
abort(403, "¡No hay autorizacion!");
}
But $roles is an array, here is the route where I use the middleware:
Route::get('/mid', ['middleware' => 'roles:super admin', function () {
return "done";
}]);
and the error that gives me is:
ErrorException in RolMiddleware.php line 22:
Invalid argument supplied for foreach()
You may thing that I do not need an array because I am only using it in super admin, for that route I only need super admin, but there would be routes that can be for super admin and the admin of an area.
In laravel , you can separate your parameters which you want to pass to middleware using comma , as follows:
Route::get('/mid', ['middleware' => 'roles:super,admin', function () {
// ^ note this
return "done";
}]);
note that, this won't send parameters as an array, so you can't loop over $roles unless you use your passed parameters as ellipsis parameters as follows :
public function handle($request, Closure $next, ...$roles)
rather, you will need to use a single parameter for each role:
public function handle($request, Closure $next, $role1, $role2) // .... and so on
Route:
Route::get('/access', ['middleware' => 'hasroles:super,admin', function () {
}]);
passing one parameter to check user have created permission in my
cause
Route::middleware('admin')->namespace('Admin')->prefix('admin')->group(function(){
Route::get('/home', 'MainController#getIndex')->name('admin.index')->middleware("hasrole:create");
Middleware:
1.Using Parameters
public function handle($request, Closure $next, $parm1, $parm2){}
2.Using var-arg
public function handle($request, Closure $next, $parm1, $parm2){}
public function handle($request, Closure $next, ...$parm1){}
Two-way Middleware Use
1: Register routeMiddleware
// Within App\Http\Kernel Class...
protected $routeMiddleware = [
'hasrole' => \Illuminate\Auth\Middleware\HasRole::class,
Using:
Route::get('admin/profile', function () {
})->middleware('hasrole');
2: Not Register in routeMiddleware
Using:
use App\Http\Middleware\HasRole;
Route::get('admin/profile', function () {
//
})->middleware(HasRole::class);
Send parameter as string like as
Route::prefix('panel')->middleware('auth:admin|editor')->group(function (){
Route::get('/', [SiteController::class, 'index'])->name('site.index');
}
Program in middleware to sense this string as array
if (in_array(Auth::user()->rule, explode('|', $access))) {
return $next($request);
} else {
return redirect()->route('site.denied');
}
I don't exactly understand what your functions do, but you can try something like this:
public function handle($request, Closure $next, $roles)
{
if(is_array($roles)){
//dd($request->user());
foreach ($roles as $rol) {
if ($request->user()->getTipoUsuario($request->user()->tipo_usuario_id)->getNombreTipoUsuario() == $rol) {
return $next($request);
}
}
}else{
if($request->user()->getTipoUsuario($request->user()->tipo_usuario_id)->getNombreTipoUsuario() == $roles)
return $next($request);
}
abort(403, "¡No hay autorizacion!");
}
You can use explode function within middleware for converting string to array.
Controller:
public function __construct()
{
$this->middleware('RoleCheck:admin|user')->except(['index', 'show']);
}
Middleware:
public function handle(Request $request, Closure $next, $roles)
{
$user = Auth::user();
$roles = explode("|", $roles); // convert $roles to array
foreach ($roles as $role) {
if ($user->hasRole($role))
return $next($request);
}
return redirect('login');
}

Laravel - How to pass variables to middleware through route group?

This is my route group,
Route::group(['middleware' => 'checkUserLevel'], function () {
// my routes
});
And this is my middleware checkUserLevel,
public function handle($request, Closure $next, $level)
{
$user = Auth::user();
if ($user->level > $level) {
return redirect('testUrl');
}
return $next($request);
}
I want to pass the $level variale to middleware from route group.
Thanks.
You can simply pass multiple arguments into the middleware using a colon. Use it like:
Route::group(['middleware' => 'checkUserLevel:some_value_of_level'], function () {
// my routes
});
Now, you can have this value inside your $level variable.
public function handle($request, Closure $next, $level)
{
$user = Auth::user();
if ($user->level > $level) {
return redirect('testUrl');
}
return $next($request);
}
This would help.
Edit: 14 Dec 2018
You can also send multiple variables to middleware. You just need to seperate the values using a comma (,).
Route::group(['middleware' => 'checkUserLevel:some_value_of_level, one_more_value_to_send'], function () {
// my routes
});
And you will get the value one_more_value_to_send in the variable after $level in the middleware handler.
public function handle($request, Closure $next, $level, $another_value)
{
$user = Auth::user();
if ($user->level > $level) {
return redirect('testUrl');
}
return $next($request);
}
For more details you can refer to: Passing parameters to Middleware in Laravel 5.1
In Laravel 6.x you have to do this
add code like in your middleware
public function handle($request, Closure $next,$module=null,$right=null)
{
dd($module,$right);
return $next($request);
}
your route code like this
Route::get('/department/add', 'DepartmentController#addNew')->middleware('ManualSec:abc,xyz');
In Kernel.php register your middleware in the section of $routeMiddleware like
'ManualSec' => \App\Http\Middleware\ManualSec::class,
by calling the rout using url in my case
http://local.pms.com:8080/department/add
it will result is like:
now you can code in your middleware

Categories