The Laravel router has a great, well-polished API when you first dive into Laravel as a beginner or newcomer to the framework. What follows is not anything hidden or new, but a few tips that should help you when you’re learning Laravel 5.
The documentation is excellent, and the tips that follow supplement and piece together a few parts that will help you get a quick jumpstart on learning how to use routing in your Laravel applications.
Custom Namespaces
As outlined in the documentation, if you want a group of routes to use a namespace like App\Http\Controllers\Admin
, you can define a namespace using the fluent routing API introduced in Laravel 5.4:
1Route::namespace('Admin')->group(function () {2 // Controllers Within The "App\Http\Controllers\Admin" Namespace3});
This is exactly the technique used in the RouteServiceProvider
found in each Laravel project:
1protected function mapWebRoutes()2{3 Route::middleware('web')4 ->namespace($this->namespace)5 ->group(base_path('routes/web.php'));6}
Because the routes/web.php
file has a namespace, our Admin
namespace relatively.
To create controllers in the App\Http\Controllers\Admin
, you can run the following console command:
1php artisan make:controller -r Admin/UsersController
Within our previous routing example, our definition might look like this in the routes/web.php
file:
1Route::namespace('Admin')2 ->prefix('admin')3 ->group(function () {4 Route::resource('users', 'UsersController');5 });
Route Macros
The Router is macroable, which means if you have a group of routes that you want to provide via a package or reusable groups of route definitions, you can define a macro in a service provider.
For example, maybe you have some shopping route for an e-commerce store that you ship as a package, and allow users to override or customize some parts of the routes:
1// Inside a service provider boot() 2 3public function boot() 4{ 5 Route::macro('shopRoutes', function ($prefix) { 6 Route::group([ 7 'prefix' => $prefix, 8 'middleware' => ['shopping'], 9 ], function () {10 Route::get('products/{product}', 'ProductsController@show');11 // ...12 });13 });14}
Then the consumer could call the macro in a new Laravel application within routes/web.php
:
1collect(config('languages'))->each(function ($language) {2 Route::shopRoutes($language);3});
Or perhaps an alternate implementation might look like:
1Route::macro('shopRoutes', function ($languages) { 2 Route::group([ 3 'prefix' => '/{language}', 4 'middleware' => ['shopping'], 5 'where' => ['language' => implode('|', $languages)], 6 ], function () { 7 Route::get('products/{product}', 'ProductsController@show'); 8 // ... 9 });10});
The macro examples are abstract, but you get the idea. I would suggest that you only use route macros if it makes sense to your use-case. You’ll know when the timing is right!
Debugging Routes
I appreciate that in a Laravel application, the web.php
file (and api.php
file) is a self-documenting file about the routes to which my application is capable of responding. I prefer to define every route instead of using resources because I appreciate the documentation aspect of this file.
If you find yourself trying to find a route or debugging all possible defined routes, the artisan route:list
command is helpful:
1artisan route:list2+--------+----------+----------+------+---------+--------------+3| Domain | Method | URI | Name | Action | Middleware |4+--------+----------+----------+------+---------+--------------+5| | GET|HEAD | / | | Closure | web |6| | GET|HEAD | api/user | | Closure | api,auth:api |7+--------+----------+----------+------+---------+--------------+
The route:list
command is useful to see the name of the route and the attached middleware. Which brings me to the next tip, naming routes.
Named Group Routes
A common convention in Laravel is naming routes, which allows you to easily reference the name of the route and avoid hard-coding the root-relative URI in your templates. In some applications hard-coding the URI is fine, in other cases, the named routes allow the following:
1{{ route('admin.users.show', ['user' => $user]) }}2{{-- /admin/users/2 --}}
When you are defining a group of routes, for example, our admin example, you can also prefix the name of the route on the group:
1Route::namespace('Admin')2 ->prefix('admin')3 ->name('admin.')4 ->group(function () {5 Route::resource('users', 'UsersController');6 });
The above prefixed name would generate route names like the following for the users
resource controller:
- admin.users.index
- admin.users.store
- admin.users.create
- admin.users.show
- admin.users.update
- admin.users.destroy
- admin.users.edit
Learn More
Read through the entire routing documentation and the resource controllers section of the controllers documentation. I reference the resource controllers section to try and ensure that most of my routes represent a REST verb and for route naming conventions.
Filed in:
Full stack web developer. Author of Lumen Programming Guide and Docker for PHP Developers.