Laravel Middleware / Route Groups - php

I'm fairly new to Laravel, so this question may obvious to some.
In the case of running checks per HTTP request, for example User Authentication. Is there a better, more efficient or simple correct way to run these checks. From my initial research it would seem that this could be accomplished using either MiddleWare, eg.
public function __construct()
{
$this->middleware('auth');
}
It also seems like it would be possible using routing groups, eg.
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
Is there any benefits of doing this either of these two ways? Apart from the obvious benefit of not having to put $this->middleware('auth'); in every controller auth would need to be checked.
Thanks
Edit..
After taking on your advice I attempted to utilities the route grouping to control my Auth MiddleWare. But this has seemed to have broken my site.
Route::group(['middleware' => 'auth'], function () {
Route::auth();
Route::get('/home', 'HomeController#index');
Route::get ( '/redirect/{provider}', 'SocialAuthController#redirect' );
Route::get ( '/callback/{provider}', 'SocialAuthController#callback' );
});
Am I missing something obvious?

You are almost there, just remove the Route::auth():
Route::group(['middleware' => 'auth'], function () {
Route::get('/home', 'HomeController#index');
//add more Routes here
});

The suggested options did not work for me but when I checked the laravel documentation, I found this:
Route::middleware(['web'])->group(function () {
//Your routes here
});
It works for me. Laravel 8.*

There is no real difference, personally i use groups for the standard middleware and put exceptions in the construct

Using Route group is easy for maintenance/modification , other wise you will have to remember each controller where you are using certain middle ware, of course this not a concern in a small medium sized application, but this will be hard in a large application where is lots of controller and references to middle ware.

Related

How Routes static class in Laravel are being invoked by the caller

I'm wondering how the caller script calls the following codes in Laravel.
Route::get('/', function () {
// return view('welcome');
return redirect('public');
});
Auth::routes();
Route::get('/home', 'HomeController#index');
Route::get('/download', 'routinesController#download');
You may check the web.php, or api.php in routes folder to see what I mean. This may not actually specific to Laravel but to programming as well. I just want to understand the script how it calls them.
Its called a Facade php pattern
If you open a Illuminate\Support\Facades\Facade it contains all the magic behind how it gets invoke in Laravel.
So simple way to understand is laravel use App container for it.
I hope it make sense

Laravel Wildcard Subdomain for User

I am looking to implement a whitelabel solution to my platform and need to implement wildcard subdomains for or system, the only issue is our system sits on a subdomain its self. So I need to filter out anything that comes to a specific subdomain.
// *.website.co.uk
Route::group(['domain' => '{element}.website.co.uk'], function() {
Route::get('/', function ($element) {
dd($element);
});
});
// my.website.co.uk
Route::get('/', 'PagesController#getLogin');
Route::post('/', 'PagesController#postLogin');
However using the code above I get the error:
Undefined variable: element
How would I avoid this error?
A good way is to exclude 'my' using a pattern. Put this code at the top of your routes file:
Route::pattern('element', '(?!^my$)');
Alternatively, that can go in the boot() section of your RouteSericeProvider. To give you a working solution, your code becomes the following (you can tidy up later!)
Route::pattern('element', '(?!^my$)');
Route::group(['domain' => '{element}.website.co.uk'], function() {
Route::get('/', 'PagesController#getLogin');
Route::post('/', 'PagesController#postLogin');
});
An alternative way is to match the 'my' route before matching the {element} route. However, while many do this I think it might be harder to maintain if the ordering of routes isn't clearly explained in the comments.

Adding multiple middleware to Laravel route

Per laravel doc, I can add the auth middleware as follows:
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
I've also seen middleware added as follows:
Route::group(['middleware' => ['web']], function() {
// Uses all Middleware $middlewareGroups['web'] located in /app/Http/kernel.php?
Route::resource('blog','BlogController'); //Make a CRUD controller
});
How can I do both?
PS. Any comments providing insight on what the bottom four lines of code are doing would be appreciated
To assign middleware to a route you can use either single middleware (first code snippet) or middleware groups (second code snippet). With middleware groups you are assigning multiple middleware to a route at once. You can find more details about middleware groups in the docs.
To use both (single middleware & middleware group) you can try this:
Route::group(['middleware' => ['auth', 'web']], function() {
// uses 'auth' middleware plus all middleware from $middlewareGroups['web']
Route::resource('blog','BlogController'); //Make a CRUD controller
});
You may also assign multiple middleware to the route:
Route::get('/', function () {
//
})->middleware('first', 'second');
Reference
You could also do the following using the middleware static method of the Route facade:
Route::middleware(['middleware1', 'middlware2'])
->group(function () {
// Your defined routes go here
});
The middleware method accepts a single string for one middleware, or an array of strings
for a group of middleware.
Route::middleware(['auth:api'])->middleware(['second:middleware'])
->prefix('yourPrefix')->group(function () {
//Add your routes here
});

Form validation is not displaying results on laravel

My form validation was not displaying errors on my posts/create route. I Googled the solution and found that
Route::group(['middleware' => 'web'], function() {
Route::resource('/posts','PostsController');
});
can be changed to
Route::group(['middlewareGroups' => 'web'], function() {
Route::resource('/posts','PostsController');
});
I did that and the problem is solved now. I want to ask if this is considered a good practice to change it like this?
Also if I am removing this line from my routes it is working:
Route::group(['middleware' => 'web'], function() {
Can anyone tell me what is actually happening ?
One reason can be that web middleware is applying two times in your case. Laravel by default adds web Middleware in app/Providers/RoutesServiceProvider.php and again you are adding it in your routes.php
Try it by removing web middleware from your routes.php.
Well, Laravel 5.3 documentation explains it in detail.
Here is the link.
https://laravel.com/docs/5.3/middleware#middleware-groups
But to answer your question, this line:
Route::group(['middleware' => 'web'], function() {
doesn't allow any request to access the routes inside only if they validate a condition which is inside the "web" middleware.
This is how laravel works. The doc gives more detail about each component in the framework.

Laravel 5 multiple "dashboard" route for admins and managers

(I have asked this question before, and did find a way around which worked for a while, but soon got out of hand. So now I am looking for a perfect solution to achieve this, the Laravel way.)
The problem is pretty simple, when admin goes to http://example.com/dashboard they should see the admin dashboard and when manager goes to the same link he should see the managers dashboard.
The way around that I used before was to call the pagecontroller and then depending on the user role call the relevant admin's or manager's dashboard controller.
// ROUTES.php
Route::group(['middleware' => 'auth'], function () {
Route::get('dashboard', 'PagesController#dashboard');
Route::get('users', 'PagesController#manageUsers');
});
// PagesController
public function dashboard(){
if($this->user->isAdmin()){
return $controller = app()->make('App\Http\Controllers\Admin\dashboard')->index();
}
if($this->user->isManager()){
return $controller = app()->make('App\Http\Controllers\Manager\dashboard')->index();
}
}
Now the problem with this approach is that I can no longer call the middleware on the dashboard controller because the process doesn't involve calling the kernel.
I am pretty sure there must be a way to achieve such a basic feature, I would be really grateful if someone can sort this out.
I think the reason this isn't a Laravel default feature because it kinda goes counter to what routes are supposed to represent. In other words, this isn't the Laravel Way. Why not redirect the user depending on their role?
// ROUTES.php
Route::group(['middleware' => 'auth'], function () {
Route::get('dashboard', function() {
if($this->user->isAdmin())
return redirect('/dashboard/admin');
if($this->user->isManager())
return redirect('/dashboard/manager');
return redirect('/home');
});
Route::get('dashboard/admin', 'Admin\dashboard#index');
Route::get('dashboard/manage', 'Manager\dashboard#index');
Route::get('users', 'PagesController#manageUsers');
});

Categories