CoderFunda
  • Home
  • About us
    • Contact Us
    • Disclaimer
    • Privacy Policy
    • About us
  • Home
  • Php
  • HTML
  • CSS
  • JavaScript
    • JavaScript
    • Jquery
    • JqueryUI
    • Stock
  • SQL
  • Vue.Js
  • Python
  • Wordpress
  • C++
    • C++
    • C
  • Laravel
    • Laravel
      • Overview
      • Namespaces
      • Middleware
      • Routing
      • Configuration
      • Application Structure
      • Installation
    • Overview
  • DBMS
    • DBMS
      • PL/SQL
      • SQLite
      • MongoDB
      • Cassandra
      • MySQL
      • Oracle
      • CouchDB
      • Neo4j
      • DB2
      • Quiz
    • Overview
  • Entertainment
    • TV Series Update
    • Movie Review
    • Movie Review
  • More
    • Vue. Js
    • Php Question
    • Php Interview Question
    • Laravel Interview Question
    • SQL Interview Question
    • IAS Interview Question
    • PCS Interview Question
    • Technology
    • Other

25 August, 2022

Laravel Route Grouping: 6 Techniques to Organize Routes

 Programing Coderfunda     August 25, 2022     Laravel, Laravel Tutorials     No comments   

 Laravel Routing is the feature that developers learn from the very beginning. But as their projects grow, it's getting harder to manage evergrowing routes files, scrolling to find the right Route::get() statements. Luckily, there are techniques to make the route files shorter and more readable, grouping routes and their settings in different ways. Let's take a look.

And no, I won't just talk about the general simple Route::group(), that one is the beginner level. Let's dive a bit deeper than that.


Grouping 1. Route::resource and Route::apiResource

Let's start with the elephant in the room: this is probably the most well-known grouping. If you have a typical set of CRUD actions around one Model, it's worth grouping them into a resource controller

Such controller can consist up to 7 methods (but may have fewer):

  • index()
  • create()
  • store()
  • show()
  • edit()
  • update()
  • destroy()

So if your set of routes corresponds to those methods, instead of:

1Route::get('books', [BookController::class, 'index'])->name('books.index');
2Route::get('books/create', [BookController::class, 'create'])->name('books.create');
3Route::post('books', [BookController::class, 'store'])->name('books.store');
4Route::get('books/{book}', [BookController::class, 'show'])->name('books.show');
5Route::get('books/{book}/edit', [BookController::class, 'edit'])->name('books.edit');
6Route::put('books/{book}', [BookController::class, 'update'])->name('books.update');
7Route::delete('books/{book}', [BookController::class, 'destroy'])->name('books.destroy');

... you may have just one line:

1Route::resource('books', BookController::class);

If you work with an API project, you don't need the visual forms for create/edit, so you may have a different syntax with apiResource() that would cover 5 methods out of 7:

1Route::apiResource('books', BookController::class);

Also, I advise you to consider the resource controllers even if you have 2-4 methods, and not the full 7. Just because it keeps the standard naming convention - for URLs, methods, and route names. For example, in this case, you don't need to provide the names manually:

1Route::get('books/create', [BookController::class, 'create'])->name('books.create');
2Route::post('books', [BookController::class, 'store'])->name('books.store');
3 
4// Instead, here names "books.create" and "books.store" are assigned automatically
5Route::resource('books', BookController::class)->only(['create', 'store']);

Grouping 2. Group Within a Group

Of course, everyone knows about the general Route grouping. But for more complex projects, one level of grouping may not be enough.

Realistic example: you want the authorized routes to be grouped with auth middleware, but inside you need to separate more sub-groups, like administrator and simple user.

1Route::middleware('auth')->group(function() {
2 
3 Route::middleware('is_admin')->prefix('admin')->group(function() {
4 Route::get(...) // administrator routes
5 });
6 
7 Route::middleware('is_user')->prefix('user')->group(function() {
8 Route::get(...) // user routes
9 });
10});

Grouping 3. Repeating Middleware Into Group

What if you have quite a lot of middlewares, some of them repeating in a few route groups?

1Route::prefix('students')->middleware(['auth', 'check.role', 'check.user.status', 'check.invoice.status', 'locale'])->group(function () {
2 // ... student routes
3});
4 
5Route::prefix('managers')->middleware(['auth', 'check.role', 'check.user.status', 'locale'])->group(function () {
6 // ... manager routes
7});

As you can see, there are 5 middlewares, 4 of them repeating. So, we can move those 4 into a separate middleware group, in the file app/Http/Kernel.php:

1protected $middlewareGroups = [
2 // This group comes from default Laravel
3 'web' => [
4 \App\Http\Middleware\EncryptCookies::class,
5 \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
6 \Illuminate\Session\Middleware\StartSession::class,
7 \Illuminate\View\Middleware\ShareErrorsFromSession::class,
8 \App\Http\Middleware\VerifyCsrfToken::class,
9 \Illuminate\Routing\Middleware\SubstituteBindings::class,
10 ],
11 
12 // This group comes from default Laravel
13 'api' => [
14 // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
15 'throttle:api',
16 \Illuminate\Routing\Middleware\SubstituteBindings::class,
17 ],
18 
19 // THIS IS OUR NEW MIDDLEWARE GROUP
20 'check_user' => [
21 'auth',
22 'check.role',
23 'check.user.status',
24 'locale'
25 ],
26];

So we named our group check_user, and now we can shorten the routes:

1Route::prefix('students')->middleware(['check_user', 'check.invoice.status'])->group(function () {
2 // ... student routes
3});
4 
5Route::prefix('managers')->middleware(['check_user'])->group(function () {
6 // ... manager routes
7});

Grouping 4. Same Name Controllers, Different Namespaces

Quite a common situation is to have, for example, HomeController for different user roles, like Admin/HomeController and User/HomeController. And if you use the full path in your routes, it looks something like this:

1Route::prefix('admin')->middleware('is_admin')->group(function () {
2 Route::get('home', [\App\Http\Controllers\Admin\HomeController::class, 'index']);
3});
4 
5Route::prefix('user')->middleware('is_user')->group(function () {
6 Route::get('home', [\App\Http\Controllers\User\HomeController::class, 'index']);
7});

Quite a lot of code to type with those full paths, right? That's why many developers prefer to have only HomeController::class in the route list and add something like this on top:

1use App\Http\Controllers\Admin\HomeController;

But the problem here is that we have the same controller class name! So, this wouldn't work:

1use App\Http\Controllers\Admin\HomeController;
2use App\Http\Controllers\User\HomeController;

Which one would be the "official" one? Well, one way is to change the name and assign the alias for one of them:

1use App\Http\Controllers\Admin\HomeController as AdminHomeController;
2use App\Http\Controllers\User\HomeController;
3 
4Route::prefix('admin')->middleware('is_admin')->group(function () {
5 Route::get('home', [AdminHomeController::class, 'index']);
6});
7 
8Route::prefix('user')->middleware('is_user')->group(function () {
9 Route::get('home', [HomeController::class, 'index']);
10});

But, personally, changing the name of the class on top is quite confusing to me, I like another approach: to add a namespace() for the sub-folders of the Controllers:

1Route::prefix('admin')->namespace('App\Http\Controllers\Admin')->middleware('is_admin')->group(function () {
2 Route::get('home', [HomeController::class, 'index']);
3 // ... other controllers from Admin namespace
4});
5 
6Route::prefix('user')->namespace('App\Http\Controllers\User')->middleware('is_user')->group(function () {
7 Route::get('home', [HomeController::class, 'index']);
8 // ... other controllers from User namespace
9});

Grouping 5. Separate Route Files

If you feel that your main routes/web.php or routes/api.php is getting too big, you may take some of the routes and put them into a separate file, name them however you want, like routes/admin.php.

Then, to enable that file to be included, you have two ways: I call the "Laravel way" and "PHP way".

If you want to follow the structure of how Laravel structures its default route files, it's happening in the app/Providers/RouteServiceProvider.php:

1public function boot()
2{
3 $this->configureRateLimiting();
4 
5 $this->routes(function () {
6 Route::middleware('api')
7 ->prefix('api')
8 ->group(base_path('routes/api.php'));
9 
10 Route::middleware('web')
11 ->group(base_path('routes/web.php'));
12 });
13}

As you can see, both routes/api.php and routes/web.php are here, with a bit different settings. So, all you need to do is add your admin file here:

1$this->routes(function () {
2 Route::middleware('api')
3 ->prefix('api')
4 ->group(base_path('routes/api.php'));
5 
6 Route::middleware('web')
7 ->group(base_path('routes/web.php'));
8 
9 Route::middleware('is_admin')
10 ->group(base_path('routes/admin.php'));
11});

But if you don't want to dive into service providers, there's a shorter way - just include/require your routes file into another file like you would do in any PHP file, outside of the Laravel framework.

In fact, it's done by Taylor Otwell himself, requiring the routes/auth.php file directly into Laravel Breeze routes:

routes/web.php:

1Route::get('/', function () {
2 return view('welcome');
3});
4 
5Route::get('/dashboard', function () {
6 return view('dashboard');
7})->middleware(['auth'])->name('dashboard');
8 
9require __DIR__.'/auth.php';

Grouping 6. New in Laravel 9: Route::controller()

If you have a few methods in the Controller but they don't follow the standard Resource structure, you may still group them, without repeating the Controller name for every method.

Instead:

1Route::get('profile', [ProfileController::class, 'getProfile']);
2Route::put('profile', [ProfileController::class, 'updateProfile']);
3Route::delete('profile', [ProfileController::class, 'deleteProfile']);

You can do:

1Route::controller(ProfileController::class)->group(function() {
2 Route::get('profile', 'getProfile');
3 Route::put('profile', 'updateProfile');
4 Route::delete('profile', 'deleteProfile');
5});

This functionality is available in Laravel 9, and the latest minor versions of Laravel 8.


That's it, these are the grouping techniques that, hopefully, will help you to organize and maintain your routes, no matter how big your project grows.

  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Email ThisBlogThis!Share to XShare to Facebook

Related Posts:

  • How to get a Websites Favicons in Laravel There may be times in your Laravel applications where you want to display a favicon from another website. For example, you could have a link to … Read More
  • Restructuring a Laravel Controller using Services, Events, Jobs, Actions, and more One of the top Laravel questions I hear is "How to structure the project". If we narrow it down, the largest part of it sounds like "If the logi… Read More
  • Laravel Roles and Permissions: Gates and Policies Explained In Laravel, roles and permissions have been one of the most confusing topics over the years. Mostly, because there is no documentation about it:… Read More
  • Laravel Jetstream: Add CRUD with Spatie Permission Laravel Jetstream is a starter kit that helps you not only with Auth scaffolding but with extra functionality like Teams or Two-Factor Authentic… Read More
Newer Post Older Post Home

0 comments:

Post a Comment

Thanks

Meta

Popular Posts

  • Spring boot app (error: method getFirst()) failed to run at local machine, but can run on server
    The Spring boot app can run on the online server. Now, we want to replicate the same app at the local machine but the Spring boot jar file f...
  • Log activity in a Laravel app with Spatie/Laravel-Activitylog
      Requirements This package needs PHP 8.1+ and Laravel 9.0 or higher. The latest version of this package needs PHP 8.2+ and Laravel 8 or hig...
  • Laravel auth login with phone or email
          <?php     Laravel auth login with phone or email     <? php     namespace App \ Http \ Controllers \ Auth ;         use ...
  • Vue3 :style backgroundImage not working with require
    I'm trying to migrate a Vue 2 project to Vue 3. In Vue 2 I used v-bind style as follow: In Vue 3 this doesn't work... I tried a...
  • Failed to install 'cordova-plugin-firebase': CordovaError: Uh oh
    I had follow these steps to install an configure firebase to my cordova project for cloud messaging. https://medium.com/@felipepucinelli/how...

Categories

  • Ajax (26)
  • Bootstrap (30)
  • DBMS (42)
  • HTML (12)
  • HTML5 (45)
  • JavaScript (10)
  • Jquery (34)
  • Jquery UI (2)
  • JqueryUI (32)
  • Laravel (1017)
  • Laravel Tutorials (23)
  • Laravel-Question (6)
  • Magento (9)
  • Magento 2 (95)
  • MariaDB (1)
  • MySql Tutorial (2)
  • PHP-Interview-Questions (3)
  • Php Question (13)
  • Python (36)
  • RDBMS (13)
  • SQL Tutorial (79)
  • Vue.js Tutorial (68)
  • Wordpress (150)
  • Wordpress Theme (3)
  • codeigniter (108)
  • oops (4)
  • php (853)

Social Media Links

  • Follow on Twitter
  • Like on Facebook
  • Subscribe on Youtube
  • Follow on Instagram

Pages

  • Home
  • Contact Us
  • Privacy Policy
  • About us

Blog Archive

  • September (100)
  • August (50)
  • July (56)
  • June (46)
  • May (59)
  • April (50)
  • March (60)
  • February (42)
  • January (53)
  • December (58)
  • November (61)
  • October (39)
  • September (36)
  • August (36)
  • July (34)
  • June (34)
  • May (36)
  • April (29)
  • March (82)
  • February (1)
  • January (8)
  • December (14)
  • November (41)
  • October (13)
  • September (5)
  • August (48)
  • July (9)
  • June (6)
  • May (119)
  • April (259)
  • March (122)
  • February (368)
  • January (33)
  • October (2)
  • July (11)
  • June (29)
  • May (25)
  • April (168)
  • March (93)
  • February (60)
  • January (28)
  • December (195)
  • November (24)
  • October (40)
  • September (55)
  • August (6)
  • July (48)
  • May (2)
  • January (2)
  • July (6)
  • June (6)
  • February (17)
  • January (69)
  • December (122)
  • November (56)
  • October (92)
  • September (76)
  • August (6)

  • Failed to install 'cordova-plugin-firebase': CordovaError: Uh oh - 9/21/2024
  • pyspark XPath Query Returns Lists Omitting Missing Values Instead of Including None - 9/20/2024
  • SQL REPL from within Python/Sqlalchemy/Psychopg2 - 9/20/2024
  • MySql Explain with Tobias Petry - 9/20/2024
  • How to combine information from different devices into one common abstract virtual disk? [closed] - 9/20/2024

Laravel News

  • Validate Controller Requests with the Laravel Data Package - 5/19/2025
  • Deployer - 5/18/2025
  • Transform JSON into Typed Collections with Laravel's AsCollection::of() - 5/18/2025
  • Auto-translate Application Strings with Laratext - 5/16/2025
  • Simplify Factory Associations with Laravel's UseFactory Attribute - 5/13/2025

Copyright © 2025 CoderFunda | Powered by Blogger
Design by Coderfunda | Blogger Theme by Coderfunda | Distributed By Coderfunda