Laravel: how to check middleware in blade template - laravel

i've created Middleware
php artisan make:middleware isTeacher
in App/Http/isTeacher.php i've placed the check:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class isTeacher
{
public function handle($request, Closure $next)
{
$user = Auth::user();
if($user && $user->capability == 3)
{
return $next($request);
}
else
return redirect('/login');
}
}
than, i've defined the middleware in app/Http/Kernel.php
protected $routeMiddleware = [
...
'auth.teacher' => \App\Http\Middleware\isTeacher::class,
...
];
The question is: how I check the teacher capability in blade template?
I'm trying with this:
#if (Auth::isTeacher())
but doesn't work
any help are appreciated

The blade directive only needs to return true or false, nothing else.
You could just do the following in the boot() method of the AppServiceProvider.php
Blade::if('teacher', function () {
return auth()->user() && $user->capability == 3;
});
Then you will be able to do the following in blade templates:
#teacher
Only teachers will see this
#endteacher

Well there is an issue here Middlewares are used to filter HTTP requests or its outter layer of the onion in laravel app. It is not defined to be used in blade to decide which part of html should be rendered.
You can filter a controller function to only be usable if it passes the middleware (if authenticated for example) and the controller only runs the function if it passes on the middleware.
When using Auth in blades you are not using a middleware but a facade whan you could do its use Session for your case like:
In your middleware
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class isTeacher
{
public function handle($request, Closure $next)
{
$user = Auth::user();
if($user && $user->capability == 3)
{
\session('isTeacher', true);
return $next($request);
}
return redirect('/login');
}
Then in your blades do like:
#if (Session::get('isTeacher', 0));
This will show content only to teachers, if session its not set it will fall back to 0 or false.

In this scenario, using middleware is not really the solution. I will rather suggest blade directive, which allows you to create a custom blade function like:
#author
//Do something
#else
//Something else
#endauthor
To use the above syntax, you can register a new blade directive in your AppServiceProvider.php file
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Blade::directive('author', function () {
$isAuth = false;
// check if the user authenticated is teacher
if (auth()->user() && auth()->user()->capability == 3) {
$isAuth = true;
}
return "<?php if ($isAuth) { ?>";
});
Blade::directive('endauthor', function () {
return "<?php } ?>";
});
}
}
After the above changes in the AppServiceProvider.php file, run php artisan view:clear
For a better understanding, you can refer to the documentation here

This is an improved version of Prince Lionel's answer. Pay attention to the return value of Blade::directive callback function.
#author
//Do something
#else
//Something else
#endauthor
AppServiceProvider.php
namespace App\Providers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Blade::directive('author', function () {
$isAuth = false;
// check if the user authenticated is teacher
if (auth()->user() && auth()->user()->capability == 3) {
$isAuth = true;
}
return "<?php if (" . intval($isAuth) . ") { ?>";
});
Blade::directive('endauthor', function () {
return "<?php } ?>";
});
}
}

Related

How can I use multiple middlewares on the same route name in Laravel 9?

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 =)

Laravel load middleware in routes under condition

I have a route files for my api and im using this package to cache the whole response.
routes/api.php
<?php
Route::get('/types', 'TypeController#indexType')->middleware('cacheResponse:600');
This works fine but i need to skip this middleware loading when i have a specific header in the request so i make this extra middleware
conditionalCacheResponse.php
<?php
namespace App\Http\Middleware;
use Closure;
class ConditionalCacheResponse
{
public function handle($request, Closure $next)
{
if (request()->header('Draft') != true) {
$this->middleware('cacheResponse:3600');
}
return $next($request);
}
}
and setup like this
routes/api.php
<?php
Route::get('/types', 'TypeController#indexType')->middleware('conditionalCacheResponse');
But is not working, im not sure if i can append a middleware in this way.
There's a few ways to do this, one way would be to use the handle() method of the HttpKernel to unset the CacheResponse middleware based on a check of the request header.
So in app/Http/Kernel.php, add this method:
public function handle($request)
{
if ($request->header('Draft')) {
if (($key = array_search('Spatie\ResponseCache\Middlewares\CacheResponse', $this->middleware)) !== false) {
unset($this->middleware[$key]);
}
}
return parent::handle($request);
}
I haven't checked this is working, but it should do the job.

Laravel-redirects even authenticated users to login

Before minus this question, or report a duplicate, please read it completely.
I use a default Laravel Autentification. But for some reason, it's somehow broke down.
When I try to login or register, if auth is success it redirects try to redirects me to a correct link, but but at the same time returns me to /login.
Example with dump
Debugbar after trying auth
Source files
1. My routes:
Auth::routes();
Route::get('/confirm', function () {
return view('confirm');
})->name('confirm');
Route::post('/confirm', 'EmployeeController#store')->name('addworker');
Route::get('users/{id}', 'EmployeeController#show')->where('id', '[0-9]+')->name('account');
Route::get('/home', 'HomeController#index')->name('home');
2. Changes into login and register controllers:
protected function redirectTo()
{
return route('account',['id'=> auth()->user()->id]);
}
3.Methods in a EmployeeController, that action in auth:
public function __construct()
{
$this->middleware('auth');
$this->middleware('confirmated');
}
public function show($id)
{
return view('account');
}
4. My middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use App\Employee;
class CheckConfirm
{
public function handle($request, Closure $next)
{
if (Auth::check()) {
$id = Auth::id();
$empl = Employee::where('user_id', '=', $id)->first();
Debugbar::info($empl);
if ($empl == null) {
return redirect()->route('confirm');
} else {
dump($empl);
return $next($request);
}
} else {
return redirect()->route('login');
}
}
}
What did not help me
clearing the cache and browser history including the artisan commands: cache:clear and config:clean
Disable my middleware or auth midlleware in controllers constructor
Disable all middleware in contructor led to this
Solutions in question duplicates, or in other forums
If there is not enough information in the question, you can download my entire project on GitHub: https://github.com/Vladislav2018/last.chance/

Auth::User() gives null in laravel 5.2

I am new to laravel. I am using multi authentication in my application. User and Admin are 2 type of user in my application. Iam developing change password for admin after logged in to application through admin's profile page. now I want to get logged in admin user detail so that i have use below code in my controller
if (Auth::guard('admin')->check()) {
$user = Auth::id();
echo '<pre>';
dd($user);
exit;
}
I have also add following code in controller
use App\Http\Controllers\Adminauth;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Admin;
use Session;
use DB;
use App\Http\Controllers\Controller;
use Auth;
In route.php i have write following code
Route::group(['middleware' => ['admin']], function () {
//Login Routes...
Route::auth();
Route::get('admin/profile/change_password', 'Admin\AdminController#change_password');
});
But i am not able to get admin user detail. can anyone help me to solve this problem.
Try this
public function __construct() {
$this->middleware('auth:admin');
$this->middleware(function ($request, $next) {
$user = $this->user = Auth::user();
dd($user);
});
}
In routes
Route::get('/', function () {
//return view('welcome');
return view('auth.login');
});
Auth::user() is working only under auth middleware. You may call auth middleware on controller or call it on routes, but not on both.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class YourController extends Controller
{
public function __construct()
{
$this->middleware('auth')
}
public function yourFunction(Request $request)
{
$user = \Auth::user();
dd($user);
}
}
<?php
Route::get('your-uri', function () {
$user = \Auth::user();
dd($user);
})->middleware('auth');

How do i make a page unaccessible when a session is set with middleware laravel 5.4

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

Resources