Routing changes in Laravel 5.3

(This is part of a series of posts on New Features in Laravel 5.3.)

  1. Introducing Laravel Echo: An In-Depth Walk-Through
  2. The new $loop variable in Laravel 5.3
  3. Customizing additional parameters in FirstOrCreate in Laravel 5.3
  4. The new cache() global helper in Laravel 5.3
  5. New JSON-column where() and update() syntax in Laravel 5.3
  6. Advanced operations with Collection::where in Laravel 5.3
  7. Image dimension validation rules in Laravel 5.3
  8. Customizing pagination templates in Laravel 5.3
  9. 5.3 feature announcement notes from Laracon
  10. Routing changes in Laravel 5.3
  11. Introducing Laravel Scout
  12. Introducing Laravel Passport
  13. Introducing Mailables in Laravel 5.3
  14. Directory structure changes in Laravel 5.3
  15. The new Notification system in Laravel 5.3
  16. Update to queue workers in Laravel 5.3
  17. Using Vue in Laravel 5.3, with the Vue bootstrap and sample component
  18. Defining console commands via closure in Laravel 5.3

The last few versions of Laravel have showed the way routing works shifting around a bit. This is usually a sign that we're feeling some sort of pain—something feels off—but haven't found the perfect solution yet. In 5.3, we may have found it.

Looking back: Routing changes in 5.2 #

In Laravel 5.2 we temporarily saw two separate route groups in routes.php, one for "web" and one for "API", but that went away mid-5.2.

What stuck around, though, was the idea of multiple middleware groups, and out of the box there's one for "web" routes and one for "API" routes.

The "web" group gets everything you'd expect your normal web users to need: sessions, cookies, CSRF protection, etc. The "API" group is lighter, and came by default with the "throttle" middleware, making the case for a stateless REST API.

Routing changes in 5.3 #

In 5.3, the app/Http/routes.php file has now moved to the root routes/ directory, and it's now split into two files: web.php and api.php. As you can probably guess, the routes in routes/web.php are wrapped with the web middleware group and the routes in routes/api.php are wrapped with the api middleware group.

There are a few benefits of this. First, we get the suggestion and easy implementation of the distinction between our web routes and our API routes. Second, it's now an application-level convention to have multiple routes files, which will likely free more developers up to feel comfortable organizing their routes file this way. And third, this moves the routes directory out of app/, which both makes the routes directory more accessible to new users and makes app/ a fully PSR-4-autoloaded directory, which feels just a bit pure-r.

If you want to customize this or add your own separate routes files, check out App\Providers\RouteServiceProvider for inspiration:

    public function map()



    protected function mapApiRoutes()
            'middleware' => ['api', 'auth:api'],
            'namespace' => $this->namespace,
            'prefix' => 'api',
        ], function ($router) {
            require base_path('routes/api.php');

    protected function mapWebRoutes()
            'namespace' => $this->namespace, 'middleware' => 'web',
        ], function ($router) {
            require base_path('routes/web.php');

As you can see, there's an easy syntax for wrapping the results of any given routes file with a route group and then applying whatever prefixes or middleware or whatever else that you'd like.

That's it! Enjoy!

Comments? I'm @stauffermatt on Twitter

Tags: laravel | laravel 5.3 | routing

Matt Stauffer headshot

Hi, I'm Matt Stauffer.

I'm partner & technical director at Tighten Co.

You can find me on Twitter at @stauffermatt

Like what you're reading?

I wrote an entire 450+ page book for O'Reilly: Laravel: Up and Running.

You can order the eBook or print book today.