I am just learning laravel and I am facing one issue. I am trying to work with session but it is not working.
Middleware
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
class Adminlogin {
public function handle() {
if (!$request->session()->has('userid')) {
return view('admin.auth.login');
}
// return $next($request);
}
}
Error
ErrorException in Adminlogin.php line 10: Undefined variable: request
You should pass $request & $next in arguments like this:
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
class Adminlogin {
public function handle($request, Closure $next) {
if (!$request->session()->has('userid')) {
return view('admin.auth.login');
}
return $next($request);
}
}
See more about - Defining Middlewares in Laravel
Hope this helps!
Change it to:
public function handle($request, Closure $next) {
Also, you can simply use session() helper in your case:
public function handle($request, Closure $next) {
return session()->has('userid') ? $next($request) : view('admin.auth.login');
}
Related
I want my /dashboard page to be a different panel in 2 different user types. And return to home screen if not logged in. I created 2 middlewares to check if logged in user is "employer" or "employee". Whatever I do, I can't seem to make it work, it's been 2 days. I created middlewares and routes by following some very sketchy tutorials, it may hurt your eyes, be aware.
My route:
Route::get('/dashboard', function () {
return view('welcome');
})->name('welcome');
Route::prefix('admin')->middleware([\App\Http\Middleware\isEmployer::class])->group( function () {
Route::get("/dashboard", function (){
return view("employer.dashboard");
})->name("dashboard");
});
Route::prefix('store')->middleware([\App\Http\Middleware\isEmployee::class])->group( function(){
Route::get("/dashboard", function (){
return view("employee.dashboard");
})->name("dashboard");
});
isEmployee middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class isEmployee
{
public function handle(Request $request, Closure $next)
{
if(Auth::user())
{
if (Auth::user()->role == "employee")
{
return $next($request);
}
}
return response()->view('welcome');
}
}
isEmployer middleware :
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class isEmployer
{
public function handle(Request $request, Closure $next)
{
if(Auth::user())
{
if (Auth::user()->role == "employer")
{
return $next($request);
}
}
return response()->view('welcome');
}
}
What I want to achieve is:
if not logged in : return welcome view
if logged in as employer : return employer.dashboard view
if logged in as employee : return employee.dashboard view
Let's start from some refactoring:
Make your routes/web.php a bit more readable:
Route::view('/dashboard', 'welcome')->name('welcome');
Route::prefix('admin')->name('admin.')->middleware('role:employer')->group(function() {
Route::view('/dashboard', 'employer.dashboard')->name("dashboard");
});
Route::prefix('store')->name('store.')->middleware('role:employee')->group(function() {
Route::view('/dashboard', 'employee.dashboard')->name("dashboard");
});
Now let's create a middleware that will check not only for one role, but for any role you give as a parameter:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class HasRole
{
public function handle(Request $request, Closure $next, string $role)
{
if (Auth::user()?->role != $role) {
return redirect()->route('welcome');
}
return $next($request);
}
}
Now, create an alias in your app/Http/Kernel.php so you could use it like i wrote it in routes file role:<role_here>:
protected $routeMiddleware = [
// ...
'role' => \App\Http\Middleware\HasRole::class,
];
Now for your question - how to use multiple middlewares for one route. It is simple:
$route->middleware(['middleware1', 'middleware2']);
You may attach them to groups or single routes:
Route::prefix('some_group')->middleware(['middleware1', 'middleware2'])->group(function() {
Route::view("some.view")->middleware('middleware3')->name("some.view");
});
You can read more info about Laravel's middlewares here, and understand what responsibility chain is (pattern which middleware implements) under the hood. Also take a look at SOLID principles, mainly at DRY one. Have a good day =)
I am trying to send a variable to terminate of middleware from route:
Route::group(['middleware' => 'checkUserLevel'], function () {
// my routes
});
I can get checkUserLevel in handle of middleware but I need to access in terminate method too, what should I do?
public function handle($request, Closure $next, $key)
{
dd($key); // it returns variable
}
public function terminate($request, $response)
{
//I need that variable here
}
As mentioned in documentation, if you would like to use the same instance of middleware (because by default it is using the fresh instance of middleware) you need to register the middleware as singleton.
You can register it as singleton by adding to your ServiceProvider's register method
public function register()
{
$this->app->singleton(\App\Http\Middleware\YourMiddleware::class);
}
Then you can use the class' property like the first example of lorent's answer
protected $foo;
public function handle($request, Closure $next)
{
$this->foo = 'bar';
return $next($request);
}
public function terminate($request, $response)
{
// because we cannot use `dd` here, so the example is using `logger`
logger($this->foo);
}
You can do:
protected $key;
public function handle($request, Closure $next, $key)
{
$this->key = $key;
}
public function terminate($request, $response)
{
$this->key; //access property key
}
even though this should be passed via request global. Like:
public function handle($request, Closure $next)
{
$request->input('key');
}
public function terminate($request, $response)
{
$request->input('key');
}
Edited:
Route::group(['middleware' => 'checkUserLevel'], function () {
Route::get('/test/{testparam}', function () {
});
});
public function handle($request, Closure $next)
{
$request->route('testparam');
}
public function terminate($request, $response)
{
$request->route('testparam');
}
I know this is ages old, but you could also use a static property. That saves you from having to register a singleton:
<?php
namespace App\Http\Middleware;
class MyMiddleware {
private static $key;
public function handle($request, Closure $next, $key)
{
self::$key = ($key); // it returns variable
}
public function terminate($request, $response)
{
$key = self::$key;
}
}
This works in my Laravel 5.8 application, don't see why it wouldnt' work anywhere else. Cannot say if there's any reason NOT to do this, but I don't know of one.
I'm using this myself to generate a Cache key in my handle function, and reuse the same key in my terminate function.
I want to use a terminable middleware for request logging:
<?php
namespace Illuminate\Session\Middleware;
use Closure;
use App\Helpers\Logger;
class LogRequest
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
Logger::log($request, $response, $additionalInfo)
}
}
How can I pass the $additionalInfo from the controller to the middleware?
EDIT:
Unfortunately the additional info is generated in the controller. I therefore cannot hard code it in the route middleware function
Have you try to add to kernel.php:
protected $routeMiddleware = [
......
'LogRequest'=> \App\Http\Middleware\LogRequest::class
];
in the LogRequestMiddleware:
public function handle($request, Closure $next, $additionalInfo)
{
//here you have $additionalInfo
$request->attributes->add(["info" => $additionalInfo]);
return $next($request);
}
public function terminate($request, $response)
{
dd( $request->attributes);
}
And in controller:
public function __construct()
{
$additionalInfo = "test"
$this->middleware("LogRequest:$additionalInfo");
}
I think you can set some attribute to the request object in your controller while handling it, and the request object itself will be passed to terminate($request, $response) as the first parameter. Then you can extract whatever you set in your controller and use it.
Edited: You might be able to do this
Controller
$request->attributes->add(['additionalInfo' => 'additionalInfoValue']);
Middleware
public function terminate($request, $response)
{
$additionalInfo = $request->attributes('additionalInfo' => $additionalInfo);
Logger::log($request, $response, $additionalInfo)
}
this my middleware:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckSession
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function CheckSessionPageReuestTokenFailed($request, $next)
{
if ($request->session()->has('request_failed')) {
return $next($request);
} else {
echo 'forbidden';
}
}
}
how i can use method CheckSessionPageReuestTokenFailed($request, $next)?
thanks
Why you have written this method ?. you can write this code into handle method.
public function handle($request, Closure $next)
{
if ($request->session()->has('request_failed')) {
return $next($request);
} else {
echo 'forbidden';
}
}
and also you need register this middleware into $routeMiddleware array in
app/Http/Kernel.php file.
add this line:
'CheckSession' => CheckSession::class,
read laravel documentation to know more https://laravel.com/docs/5.4/middleware
public function handle($request, Closure $next)
{
$this->CheckSessionPageReuestTokenFailed($request, $next);
return $next($request);
}
You can use inside handle() method.
public function handle($request, Closure $next)
{
$this->CheckSessionPageReuestTokenFailed($request, $next);
return $next($request);
}
I'm trying to make a page unaccessible when a session is set in laravel
The middleware i tried is App\Http\Middleware\TwoStep.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class TwoStep
{
public function handle($request, Closure $next)
{
if (Auth::user()) {
if (session('validate') === 'true') {
back();
} else {
return redirect('/auth');
}
} else {
return redirect('/login');
}
}
}
the way i tried to use the middleware :
Route::get('/auth', 'AuthController#index')->middleware('twostep');
This gave me a redirect loop though.
Unless back() is a helper you have created, it should be:
return redirect()->back();