A Guide to Using Where Constraints in Laravel Routes

Last updated 12th November, 2023

Introduction

Constraints in Laravel routes are used to restrict the parameters that can be passed to a route. This can be useful in situations where you want to ensure that only certain types of data are accepted, or when you need to limit the range of values that can be passed. Constraints are defined using regular expressions, which allow for very precise matching of input data.

In this guide, we will explore the different types of constraints that can be used in Laravel routes. We will cover basic regular expression syntax, as well as more advanced techniques such as parameter grouping and optional parameters.

Exploring the Usage of Where Constraints

Where constraints are defined in the Laravel route definition using the where method. The syntax for defining where constraints is as follows:

Route::get('/article/{id}', function ($id) {
    //
})->where('id', '[0-9]+');

In the above example, the where method is used to define a constraint on the id parameter. The constraint ensures that the id parameter only accepts numeric values.

Here's another example, where the following constraint ensures that the name parameter only accepts alphabetical characters, numerical characters, and hyphens:

Route::get('/article/{slug}', function ($name) {
    //
})->where('slug', '[A-Za-z0-9-]+');

Where constraints can be used to validate multiple parameters at once. For example, the following constraint ensures that the name parameter only accepts alphabetical values and the slug parameter only accepts alphabetical characters, numerical characters, and hyphens:

Route::get('/category/{name}/{slug}', function ($id, $name) {
    //
})->where([
    'name' => '[A-Za-z]+',
    'slug' => '[A-Za-z0-9-]+',
]);

A Simple Practical Example

A scenario where the where constraint may come in useful is where your route path can different based on business logic. For example, where you have two different words that can prefix a blog post route.

Route::get('/article/{slug}', function (string $prefix, string $slug) {
    $article = Article::query()->whereSlug($id)->firstOrFail();

    return view('article.show', [
        'article' => $article,
    ]);
});

Route::get('/post/{slug}', function (string $prefix, string $slug) {
    $article = Article::query()->whereSlug($id)->firstOrFail();

    return view('article.show', [
        'article' => $article,
    ]);
});

In the example above, we have two different paths that point to the same function. A bit clunky having to define it twice. What if we could combine these using a variable parameter?

Route::name('article.show')
    ->get('/{prefix}/{slug}', function (string $prefix, string $slug) {
        $article = Article::query()->whereSlug($id)->firstOrFail();

        return view('article.show', [
            'article' => $article,
        ]);
    })
    ->where('prefix', 'article|post');

Now, the show post route can accept either /article/my-post-slug, or /post/my-post-slug as valid paths to the resource. Anything else will 404 as usual. Pretty niche, but handy when you need it.

Watch Out For Your Route Order

The order in which you define routes matters. If you defined a route that for whatever reason matched a similar path to the example above, the url would be picked up by that route before this one.

It important when using niche cases like this to consider the implications on your wider application. In the example above we're matching against potentially any root URL, so care needs to be taken to make sure it's correctly oredred.

Conclusion

Most of the time this feature will be pretty niche, you won't need it all the time. However, there are times where it fills a requirement, and you can use it to build some interesting new ways of handling your controller logic.

No comments yet…

DevInTheWild.

Login To Add Comments.

Want More Like This?

Subscribe to occasional updates.

Related Articles