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

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

Related

Passing data from controller to middleware laravel

I have a problem when I want to pass data to the view via the middleware to count the number of users. when not using middleware, variable from controller get to the view.
my HomeController.php
public function index()
{
$count = User::count();
return view('admin.Dashboard', compact($count);
}
my Middleware
public function handle(Request $request, Closure $next)
{
if ($request->user() && $request->user()->role == 'admin') {
return response()->view('admin.Dashboard');
} else {
return response()->view('member.dashboard');
}
return $next($request);
}
the $count variable if using middleware in route not passed to the view
my web.php
Auth::routes(['verify' => true]);
Route::get('/dashboard', 'HomeController#index')->middleware('verified', 'cekrole')->name('home');
In your middleware you are returning response (a view), so
return $next($request);
will never be executed, so neither will your controller.
User call /dashboard > Your middleware is called > if it's an admin you are returning admin.Dashboard, else member.dashboard.
But you never execute code in your Controller.
As a quick fix you could replace your Middleware by :
public function handle(Request $request, Closure $next)
{
if ($request->user() && $request->user()->role == 'admin') {
$count = User::count();
return view('admin.Dashboard', compact('count'));
}
return response()->view('member.dashboard');
}
or make those test (admin/not admin) in your controller

Handling Admin and User Authentication - Laravel

I have 2 two users (Admin and operators) for my system and i want to authenticate them to their various pages based on their roles. I am using the Authenticated.php middleware to achieve this job like below
but i get an error when trying to login with any of the users as
Call to undefined method Illuminate\Contracts\Auth\Factory::check()
What am i doing wrong please?
Authenticated.php
public function handle($request, Closure $next, ...$guards)
{
if(Auth::check()) {
if(Auth::user()->hasRole('administrator')) {
return redirect('/');
} else if (Auth::user()->hasRole('operator')) {
return redirect('client/dashboard');
}
}
// $this->authenticate($guards);
return $next($request);
}
Route.php
Route::group(['middleware' => ['auth']], function () {
Route::get('/', 'PagesController#dashboard');
});
Route::group(array('prefix' => 'client', 'namespace' => 'User', 'middleware' => ['auth']), function () {
Route::get('/dashboard', 'DashboardController#create');
});
Aren't you messing up with your if condition? Try the below code in your RedirectIfAuthenticated.php file in App\Http\Middleware. Hope that will resolve your problem.
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
if(Auth::user()->hasRole('administrator'))
{
return redirect('/');
}
else
{
return redirect('client/dashboard');
}
}
return $next($request);
}
And Are you using Entrust for handling roles?

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');
}

How to use 'OR' middleware for route laravel 5

I've two types for user and I've created multiple middlewares.
Some routes need to allow for both type of user.
I've trying following code:
Route::group(['namespace' => 'Common', 'middleware' => ['Auth1', 'Auth2']], function() {
Route::get('viewdetail', array('as' => 'viewdetail', 'uses' => 'DashboardController#viewdetail'));
});
But its not working :(
Middleware is supposed to either return a response or pass the request down the pipeline. Middlewares are independent of each other and shouldn't be aware of other middlewares run.
You'll need to implement a separate middleware that allows 2 roles or single middleware that takes allowed roles as parameters.
Option 1: just create a middleware is a combined version of Auth1 and Auth2 that checks for 2 user types. This is the simplest option, although not really flexible.
Option 2: since version 5.1 middlewares can take parameters - see more details here: https://laravel.com/docs/5.1/middleware#middleware-parameters. You could implement a single middleware that would take list of user roles to check against and just define the allowed roles in your routes file. The following code should do the trick:
// define allowed roles in your routes.php
Route::group(['namespace' => 'Common', 'middleware' => 'checkUserRoles:role1,role2', function() {
//routes that should be allowed for users with role1 OR role2 go here
});
// PHP < 5.6
// create a parametrized middleware that takes allowed roles as parameters
public function handle($request, Closure $next) {
// will contain ['role1', 'role2']
$allowedRoles = array_slice(func_get_args(), 2);
// do whatever role check logic you need
}
// PHP >= 5.6
// create a parametrized middleware that takes allowed roles as parameters
public function handle($request, Closure $next, ...$roles) {
// $roles will contain ['role1', 'role2']
// do whatever role check logic you need
}
This example
How to pass multiple parameters to middleware with OR condition in Laravel 5.2
Instead of adding multiple arguments to your handle method and having to update it every time you add a new role to your application, you can make it dynamic.
Middleware
/**
* Handle an incoming request.
*
* #param $request
* #param Closure $next
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function handle($request, Closure $next) {
$roles = array_slice(func_get_args(), 2); // [default, admin, manager]
foreach ($roles as $role) {
try {
Role::whereName($role)->firstOrFail(); // make sure we got a "real" role
if (Auth::user()->hasRole($role)) {
return $next($request);
}
} catch (ModelNotFoundException $exception) {
dd('Could not find role ' . $role);
}
}
Flash::warning('Access Denied', 'You are not authorized to view that content.'); // custom flash class
return redirect('/');
}
Route
Route::group(['middleware' => ['role_check:default,admin,manager']], function() {
Route::get('/user/{user_id}', array('uses' => 'UserController#showUserDashboard', 'as' => 'showUserDashboard'));
});
This will check if the authenticated user has at least one of the roles provided and if so, passes the request to the next middleware stack. Of course the hasRole() method and the roles themselves will need to be implemented by you.
You can use php 5.6
public function handle($request, Closure $next, ...$roles)
{
foreach ($roles as $role) {
try {
if ($request->user()->can($role)) {
return $next($request);
}
} catch (ModelNotFoundException $exception) {
abort(403);
}
}
}
Route::group(['middleware' => 'role:manager,admin'], function () {}
In middleware named 'role' you can destruct arguments into array
public function handle($request, Closure $next, ...$roles)
{
$userRole = $request->user()->role;
if (! $userRole || ! in_array($userRole->name, $roles)) {
abort(403);
}
return $next($request);
}
simply You can use like this syntax that means if has one of them
Route::group(['middleware' => ['role:first|second|third|....']], function () {});

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

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);
}

Categories