Mastering Laravel Routing – Part 5

aravel Laravel Views & Blade Templates – Beginner’s Guide

Laravel Routing: Named Routes, Route Groups & Model Binding

Laravel provides powerful routing features that make your applications clean, readable, and flexible. In this tutorial, we’ll cover Named Routes, Route Groups, and Route Model Binding (implicit, explicit, and customized).


Named Routes

Named routes let you generate URLs and redirects using route names instead of hardcoding paths.

Defining a Named Route

Route::get('/user/profile', function () {
    return 'User Profile';
})->name('profile');

Or for controllers:

Route::get('/user/profile', [UserProfileController::class, 'show'])->name('profile');

Route names must be unique.

Generating URLs & Redirects

$url = route('profile');                 // Generate URL
return redirect()->route('profile');     // Redirect
return to_route('profile');              // Shortcut redirect

With Parameters

Route::get('/user/{id}/profile', fn($id) => "User $id")->name('profile');

$url = route('profile', ['id' => 1]);  
// /user/1/profile

Extra values become query strings:

$url = route('profile', ['id' => 1, 'photos' => 'yes']);
// /user/1/profile?photos=yes

Inspecting the Current Route

You can check the current route name in middleware or controllers:

public function handle(Request $request, Closure $next)
{
    if ($request->route()->named('profile')) {
        // Perform action if "profile" route
    }
    return $next($request);
}

Route Groups

Route groups let you share attributes (middleware, prefix, name, etc.) across multiple routes.

Middleware for Groups

Route::middleware(['auth', 'verified'])->group(function () {
    Route::get('/dashboard', fn() => 'Dashboard');
    Route::get('/settings', fn() => 'Settings');
});

Controller Groups

use App\Http\Controllers\OrderController;

Route::controller(OrderController::class)->group(function () {
    Route::get('/orders/{id}', 'show');
    Route::post('/orders', 'store');
});

Subdomain Routing

Route::domain('{account}.example.com')->group(function () {
    Route::get('/user/{id}', fn($account, $id) => "Account: $account, User: $id");
});

Route Prefix

Route::prefix('admin')->group(function () {
    Route::get('/users', fn() => 'Admin Users');
});
// URL: /admin/users

Route Name Prefix

Route::name('admin.')->group(function () {
    Route::get('/users', fn() => 'Users')->name('users');
});
// Route name = admin.users

Route Model Binding

Instead of fetching models manually, Laravel can inject models directly into routes.

Implicit Binding

use App\Models\User;

Route::get('/users/{user}', function (User $user) {
    return $user->email;
});
  • {user} matches the $user variable.
  • If no user is found → 404.

In Controllers

Route::get('/users/{user}', [UserController::class, 'show']);

public function show(User $user) {
    return view('user.profile', compact('user'));
}

Soft Deleted Models

Allow binding of trashed models:

Route::get('/users/{user}', fn(User $user) => $user)->withTrashed();

Customizing the Key

Use a column other than id:

Route::get('/posts/{post:slug}', fn(Post $post) => $post);

Or override in model:

public function getRouteKeyName(): string {
    return 'slug';
}

Scoped Bindings

Bind nested resources automatically:

Route::get('/users/{user}/posts/{post:slug}', fn(User $user, Post $post) => $post);
  • Laravel assumes User has a posts relationship.

Enable globally:

Route::scopeBindings()->group(function () {
    Route::get('/users/{user}/posts/{post}', fn(User $u, Post $p) => $p);
});

Disable with:

->withoutScopedBindings()

Handling Missing Models

Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])
    ->name('locations.view')
    ->missing(fn(Request $r) => Redirect::route('locations.index'));

Enum Binding

Use PHP 8.1 Enums in routes:

enum Category: string {
    case Fruits = 'fruits';
    case People = 'people';
}

Route::get('/categories/{category}', fn(Category $category) => $category->value);
  • Works only if value matches enum, else → 404.

Explicit Model Binding

Define model binding manually in AppServiceProvider:

use App\Models\User;

public function boot(): void {
    Route::model('user', User::class);
}

Now:

Route::get('/users/{user}', fn(User $user) => $user);

Custom Resolution Logic

Route::bind('user', function ($value) {
    return User::where('name', $value)->firstOrFail();
});

Or inside the model:

public function resolveRouteBinding($value, $field = null) {
    return $this->where('name', $value)->firstOrFail();
}

For child models:

public function resolveChildRouteBinding($childType, $value, $field) {
    return parent::resolveChildRouteBinding($childType, $value, $field);
}

Important

  • Named Routes → Generate URLs/redirects easily with route() and redirect()->route().
  • Route Groups → Share middleware, prefixes, controllers, and domains.
  • Route Model Binding → Automatically inject models (implicit, explicit, or customized).
  • Supports soft deletes, custom keys, enums, scoped bindings, and custom missing behavior.