What is routing in Laravel?

In this article, I will discuss those aspects of Laravel’s route that are essential for creating a Laravel web application. We can learn about routing in Laravel in detail from the documentation of Laravel and its URL is: https://laravel.com/docs/10.x/routing.

Overview

In Laravel, route is used to create a request URL in our application. In Laravel, routes are defined in routes files, and routes files are stored in the routes directory. Routes for web applications are defined in the routes/web.php file and routes for API are defined in the routes/api.php file.

Define Route

We can define routes by using closure or we can do it using a method of any controller class. We will see this with an example.

Let’s say we want to access this URL http://<SITEURL>/user in our web application then we can define the route by following the below processes.

Using Closure

We can write the below syntax by using closure for the above URL in the routes/web.php file.

path: routes\web.php

use Illuminate\Support\Facades\Route;
 
Route::get('/user', function () {
    return 'Hi';
});

Using controller method

We can write the below syntax by using the controller method for the above URL in the routes/web.php file. Here user route is defined to the index method of the UserController.

use Illuminate\Support\Facades\Route;
 
use App\Http\Controllers\UserController;
 
Route::get('/user', [UserController::class, 'index']);

Available router methods

HTTP methods

We can use HTTP methods like, get, post, put, patch, delete, and options to register routes for our application. The syntax of these routes is as follows.

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

To register a route that responds to multiple HTTP methods, we can use the match method.

Route::match(['get', 'post'], '/', function () {
    // ...
});

To register a route that responds to all HTTP methods, we can use the any method.

Route::any('/', function () {
    // ...
});

Redirect Routes

To define a route that redirects to another URI, we may use the Route::redirect method. the syntax is as follows.

Route::redirect('/here', '/there');

To define a route that redirects to another URI with a 301 status code, we may use the Route::permanentRedirect method.

Route::permanentRedirect('/here', '/there');

View Routes

If we want to return only a view we may use the Route::view method. In the following example, the userview.blade.php file should be in the resources/view folder.

Route::view('/user', 'userview');

Route Parameters

Route parameters could be required or optional.

Required Parameters

We can define route parameters to capture a segment of the URI within our route. Let’s say we want to access the URL http://<SITEURL>/posts/1/comments/2 and want to capture post id (1) and comment id (2) in our web application then we can define the route by following syntax.

use Illuminate\Support\Facades\Route;
 
Route::get('/posts/{post}/comments/{comment}', function (string $postId, string $commentId) {
    return 'Post ID: '.$postId. ' and Comment ID: '.$commentId;
});

Optional Parameters

We may need to specify a route parameter that may not always be present in the URL and for that, we may place a ? mark after the parameter name.

Let’s say we want to access the URL http://<SITEURL>/user/ or http://<SITEURL>/user/john and want to capture the name (empty string or john) in our web application then we can define the route by following syntax.

use Illuminate\Support\Facades\Route;
 
Route::get('/user/{name?}', function (?string $name = null) {
    return $name;
});

Named Routes

Named routes are very useful if we want to generate a URL in our application or if we want to redirect to a particular route from our application. For that, we need to chain the name method in the route definition.

As an example, if a user logs in from our application, we will redirect him to the http://<SITEURL>/profile URL. First, we will define the route and for that, we can use the following syntax.

use Illuminate\Support\Facades\Route;

Route::get('/profile', function () {
    // ...
})->name('profile');

Now, we can use the route’s name, i.e. profile, when generating URLs or redirecting. In the following example, we have used route and redirect helper functions.

namespace App\Http\Controllers;

class UserController extends Controller {

    public function login(){
	
	// If login successful then redirecting to profile
	
	// Generating URL if needed
	// $url = route('profile');

	// Redirecting
	return redirect()->route('profile');	

    }

}

If the named route defines parameters, we can pass the parameters in an array as the second argument to the route function. For this, we will define the route as a named route that we defined in the discussion of Required Parameters mentioned above.

use Illuminate\Support\Facades\Route;
 
Route::get('/posts/{post}/comments/{comment}', function (string $postId, string $commentId) {
    return 'Post ID: '.$postId. ' and Comment ID: '.$commentId;
})->name('commentDetails);

Now from the controller, if we write the following code then postId and commentId will automatically be inserted into the generated URL.

$url = route('commentDetails', ['postId' => 1, 'commentId' => '2']);

This will create the URL: http://<SITEURL>/posts/1/comments/2 and we can access this URL in our application through the commentDetails route.

Dependency Injection

Dependency Injection means that the class dependencies are injected into the class via the constructor or, in some cases, “setter” methods. The Laravel service container will resolve and inject the declared dependencies into this callback. I have discussed this topic in one of my earlier articles – https://webtechbased.com/what-is-service-container-in-laravel/. Here I will discuss how to type-hint a class while defining a route.

use Illuminate\Support\Facades\Route;

use Illuminate\Http\Request;

Route::get('/user', function (Request $request) {
    
    return 'Hi '. $request->name . ', your id is: '. $request->id;

});

Now if we access the URL: http://<SITEURL>/user?id=1&name=dev, the browser will output: Hi dev, your id is: 1

If we define a route with parameters and inject a dependency on that route, the callback method of the route must list the dependencies first and then the parameters. We will understand this with an example.

Let’s say we want to access the URL http://<SITEURL>/user/1?name=dev. For this, we will define a route first.

use Illuminate\Support\Facades\Route;

use Illuminate\Http\Request;

Route::get('/user/{id}', function (Request $request, $id) {
    
    return 'Hi '. $request->name . ', your id is: '. $id;

});

In the above route definition, we have listed the dependency first (Request $request) and then the parameter ($id). Now, if we browse http://<SITEURL>/user/1?name=dev we get the output in the browser: Hi dev, your id is: 1

Route Groups

Route groups are a way of sharing route attributes, like middleware, between many routes and do not require defining these attributes on each route.

Group by middlewares

We can use the middleware method to assign middleware to all routes within a group. In the following example, both the profile and the gallery route will be executed.

Middlewares are executed in the order they are listed in the array, i.e. in the following example, for the profile and the gallery route the first middleware will be executed first then the second middleware will be executed.

use Illuminate\Support\Facades\Route;

Route::middleware(['first', 'second'])->group(function () {
     
    Route::get('/profile', function () {
        
    });

    Route::get('/gallery', function () {
        
    });

});

Group by controllers

We can use the controller method to utilize the same controller for all routes within a group. In the following example, for the routes within the group utilize the PostController.

use Illuminate\Support\Facades\Route;

use App\Http\Controllers\PostController;
 
Route::controller(PostController::class)->group(function () {
    Route::get('/posts/{id}', 'show');
    Route::post('/posts', 'store');
});

Group by prefixes

We can use the prefix method to prefix each route in the group. In the following example, we have added a prefix (admin) to all route URIs within the group.

Route::prefix('admin')->group(function () {

    Route::get('/users', function () {
        
    })->name('users');

    Route::get('/products', function () {
        
    })->name('products');

});

Here, the users route matches the http://<SITEURL>/admin/users URL and the products route matches the http://<SITEURL>/admin/products URL.

Group by name prefixes

We can use the name method to prefix each route name in the group with a given string. In the following example, we have added a name prefix with the trailing . character in the prefix (admin.) to all route URLs within the group.

Route::name('admin.')->group(function () {

    Route::get('/users', function () {
        
    })->name('users');

    Route::get('/products', function () {
        
    })->name('products');

});

Here, the users route matches the http://<SITEURL>/admin.users URL and the products route matches the http://<SITEURL>/admin.products URL.

Route Model Binding

Using Laravel route model binding we can inject model instances directly into our routes. For example, we can inject the entire User model instance that matches the given ID instead of injecting a user’s ID.

Implicit Binding

If we define Eloquent models in routes or controller actions then Laravel would resolve that model whose type-hinted variable names match a route segment name.

We will understand this with the following example.

use Illuminate\Support\Facades\Route;

use App\Models\User;
 
Route::get('/users/{user}', function (User $user) {
    return $user->email;
});

In the above example, we have type-hinted $user variable as the App\Models\User Eloquent model. Now if we browse http://<SITEURL>/users/1, the above route will access this URL, and {user} will capture 1 of the URI segments. Here Laravel will inject the User model instance that has an ID of 1 in the users table of the database.

We can resolve Eloquent models using a column other than id. For that, we can specify the column in the route parameter definition. In the following example, we will resolve the User model using email.

use Illuminate\Support\Facades\Route;

use App\Models\User;
 
Route::get('/users/{user:email}', function (User $user) {
    return $user->name;
});

A 404 HTTP response will be returned if a matching model instance is not found in the database.

We can use implicit binding for controller methods. For this, the route and the controller will be as follows.

path: routes\web.php

use Illuminate\Support\Facades\Route;

use App\Http\Controllers\UserController;
 
Route::get('/users/{user}', [UserController::class, 'show']);

path: app\Http\Controllers\UserController.php

<?php

namespace App\Http\Controllers;

use App\Models\User;

class UserController extends Controller
{
    public function show(User $user){

        return $user->name;

    }

}

Explicit Binding

In Laravel we can use Explicit Binding to bind eloquent models. We can explicitly define how route parameters correspond to eloquent models in Laravel. For that, we need to use the router’s model method within the boot method of the RouteServiceProvider class.

path: app\Providers\RouteServiceProvider.php

namespace App\Providers;

use Illuminate\Support\Facades\Route;

use App\Models\User;

class RouteServiceProvider extends ServiceProvider
{
    // ...

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

        // ...
    }
}

Now in the entire application user parameter will correspond with the User model.

We can now define the user route as follows.

use Illuminate\Support\Facades\Route;

Route::get('/users/{user}', function ($user) {
    return $user->email;
});

In the above route definition, we used explicit model binding. As the user parameter corresponds with the User model we have used the $user variable in the closure function above.

Now if we browse http://<SITEURL>/users/1, a User model instance will be injected that has an id of 1 in the database.

If no matching record is found in the database a 404 HTTP response will be generated.

Fallback Routes

Laravel will render a 404 page when no matching route is found for an incoming request through the application’s exception handler.

But we can define a route using the route’s fallback method to override the default 404 page when no route is matched for incoming requests.

We should define the fallback route after defining all the routes in the routes/web.php file.

Route::fallback(function () {
    return "custom 404";
});

Now if we browse http://<SITEURL>/userszzz, we will get “custom 404” instead of the default 404 page.

Accessing Current Route

To access the current route instance we can use the current method of the Route facade.

$route = Route::current(); // Illuminate\Routing\Route

To access the current route name we can use the currentRouteName method of the Route facade. If no name is given when defining the route, this will return null.

$name = Route::currentRouteName(); // string

To access the current route action we can use the currentRouteAction method of the Route facade.

$action = Route::currentRouteAction(); // string

If we have defined a route to the show method of the user controller, then for the above syntax within the show method, we will get the action as: App\Http\Controllers\UserController@show. The code of the route and the controller is as follows.

path: routes\web.php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;

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

path: app\Http\Controllers\UserController.php

namespace App\Http\Controllers;

use App\Models\User;

use Illuminate\Support\Facades\Route;

class UserController extends Controller
{
    public function show(User $user){
        $action = $route = Route::currentRouteAction(); // string
        dump($action);    
    }

}

In this article, I have discussed the various features of Laravel’s route that I think are essential for any Laravel project. I hope you will like the above article.