1. Отдельные маршруты WEB и API
Это легко, так как Laravel поставляется с этой функцией по умолчанию. Есть два файла:
Поэтому, если в вашем проекте есть как визуальные веб-страницы, так и API (что в наши дни встречается все чаще и чаще), поместите маршруты API в этот отдельный файл.
Например, если у вас есть страница /users, а затем конечная точка /api/users/, разделение их на отдельные файлы поможет избежать путаницы с одинаковыми именами в одном и том же файле.
Тем не менее, я недавно видел контр-интуитивный пример из официального проекта Laravel. В Laravel Horizon у Тейлора есть только маршруты API, и он не использовал отдельный файл, а поместил его в route/web.php :

Еще одно доказательство того, что структурирование в Laravel очень личное и нет 100% стандарта, даже от самого Тейлора.
2. Структурируйте файл route/web.php по группам
Это также происходит из «базового» Laravel — группировки маршрутов. Это пример из официальной документации Laravel:
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Uses first & second Middleware
});
Route::get('user/profile', function () {
// Uses first & second Middleware
});
});
Самое простое использование — скрытие разных групп под разным промежуточным ПО. Например, вы хотите, чтобы одна группа была ограничена промежуточным программным обеспечением аутентификации по умолчанию, другая группа — отдельным промежуточным программным обеспечением администратора и т. д.
При этом вы также можете использовать имена и префиксы групп маршрутов. Опять же, несколько примеров из официальной документации:
Route::prefix('admin')->group(function () {
Route::get('users', function () {
// Matches The "/admin/users" URL
});
});
Route::name('admin.')->group(function () {
Route::get('users', function () {
// Route assigned name "admin.users"...
})->name('users');
});
Кроме того, если вы хотите добавить все промежуточное ПО + имя + префикс в одну группу, более читабельно поместить их в массив:
// Instead of chaining like this:
Route::name('admin.')->prefix('admin')->middleware('admin')->group(function () {
// ...
});
// You can use an array
Route::group([
'name' => 'admin.',
'prefix' => 'admin',
'middleware' => 'auth'
], function () {
// ...
});
Давайте свяжем все это вместе с реальным примером и тремя группами:
- Группа «Гость» с URL-адресами /front/XXXXX и без промежуточного ПО;
- Группа «Пользователь» с URL-адресами /user/XXXXX и промежуточным ПО для аутентификации;
- Группа «Администратор» с URL-адресами /admin/XXXXX и пользовательским промежуточным ПО для администрирования.
Вот способ сгруппировать все это в файле route/web.php:
Route::group([
'name' => 'admin.',
'prefix' => 'admin',
'middleware' => 'admin'
], function () {
// URL: /admin/users
// Route name: admin.users
Route::get('users', function () {
return 'Admin: user list';
})->name('users');
});
Route::group([
'name' => 'user.',
'prefix' => 'user',
'middleware' => 'auth'
], function () {
// URL: /user/profile
// Route name: user.profile
Route::get('profile', function () {
return 'User profile';
})->name('profile');
});
Route::group([
'name' => 'front.',
'prefix' => 'front'
], function () {
// No middleware here
// URL: /front/about-us
// Route name: front.about
Route::get('about-us', function () {
return 'About us page';
})->name('about');
});
3. Группировка контроллеров с помощью пространств имен
В приведенном выше примере мы не использовали контроллеры, мы просто вернули статический текст в качестве примера. Давайте добавим контроллеры, но с еще одной «изюминкой» — мы будем структурировать их по папкам с разными пространствами имен, например так:

И затем мы можем использовать их в нашем файле Routes:
Route::group([
'name' => 'front.',
'prefix' => 'front'
], function () {
Route::get('about-us', 'Front\AboutController@index')->name('about');
});
Но что, если у нас много контроллеров в этой группе? Должны ли мы постоянно добавлять Front\SomeController? Конечно нет. Вы также можете указать пространство имен в качестве одного из параметров.
Route::group([
'name' => 'front.',
'prefix' => 'front',
'namespace' => 'Front',
], function () {
Route::get('about-us', 'AboutController@index')->name('about');
Route::get('contact', 'ContactController@index')->name('contact');
});
4. Группа внутри группы
Ситуация выше с тремя группами упрощена, реальные проекты имеют немного другую структуру — из двух групп: front и auth. А дальше внутри auth есть подгруппы: user и admin. Для этого мы можем создать подгруппы в route/web.php и назначить различные промежуточные программы/префиксы и т. д.
Route::group([
'middleware' => 'auth',
], function() {
Route::group([
'name' => 'admin.',
'prefix' => 'admin',
'middleware' => 'admin'
], function () {
// URL: /admin/users
// Route name: admin.users
Route::get('users', 'UserController@index')->name('users');
});
Route::group([
'name' => 'user.',
'prefix' => 'user',
], function () {
// URL: /user/profile
// Route name: user.profile
Route::get('profile', 'ProfileController@index')->name('profile');
});
});
Мы можем сделать это даже с более чем двумя уровнями, вот пример из проекта с открытым исходным кодом Akaunting:
Route::group(['middleware' => 'language'], function () {
Route::group(['middleware' => 'auth'], function () {
Route::group(['prefix' => 'uploads'], function () {
Route::get('{id}', 'Common\Uploads@get');
Route::get('{id}/show', 'Common\Uploads@show');
Route::get('{id}/download', 'Common\Uploads@download');
});
Route::group(['middleware' => 'permission:read-admin-panel'], function () {
Route::group(['prefix' => 'wizard'], function () {
Route::get('/', 'Wizard\Companies@edit')->name('wizard.index');
// ...
Другой пример — из другой популярной CRM Laravel под названием Monica :
Route::middleware(['auth', 'verified', 'mfa'])->group(function () {
Route::name('dashboard.')->group(function () {
Route::get('/dashboard', 'DashboardController@index')->name('index');
Route::get('/dashboard/calls', 'DashboardController@calls');
Route::get('/dashboard/notes', 'DashboardController@notes');
Route::get('/dashboard/debts', 'DashboardController@debts');
Route::get('/dashboard/tasks', 'DashboardController@tasks');
Route::post('/dashboard/setTab', 'DashboardController@setTab');
});
5. Глобальные настройки в RouteServiceProvider
Есть файл, который служит для всех настроек маршрутов — app/Providers/RouteServiceProvider.php. У него есть метод map(), где он связывает оба файла маршрутов — веб и API:
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
Вы заметили , что промежуточное ПО, пространство имен и префикс упоминаются в методах? Здесь вы можете установить глобальные настройки для всего файла, чтобы вам не пришлось повторять их для каждой группы маршрутов внутри файла.
В основном он используется для маршрутов API, поскольку их настройки обычно одинаковы, например:
protected function mapApiRoutes()
{
Route::group([
'middleware' => ['api'],
'namespace' => $this->namespace,
'prefix' => 'api/v1',
], function ($router) {
require base_path('routes/api.php');
});
}
Этот вышеприведенный метод будет ставить перед всеми URL-адресами API префикс api/v1/ в начале.
6. Группировка в дополнительные файлы — стоит ли?
Если у вас огромное количество маршрутов и вы хотите сгруппировать их еще больше, в отдельные файлы, то вы можете использовать тот же файл, упомянутый в предыдущем разделе — app/Providers/RouteServiceProvider.php. Если вы внимательно посмотрите на его методы map(), вы увидите закомментированное место в конце:
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
//
}
Вы можете интерпретировать это как своего рода «приглашение» добавить больше файлов, если хотите. Таким образом, вы можете создать другой метод, такой как mapAdminRoutes() внутри этого файла, а затем добавить его в метод map(), и ваш отдельный файл будет зарегистрирован и загружен автоматически.
Но лично я не вижу особых преимуществ в этом подходе и нечасто встречал его. Это дает немного больше разделения маршрутов, но иногда вы теряетесь в этих файлах и не знаете, где искать конкретный маршрут.
7. Найдите точный маршрут с помощью команды Artisan route:list
Говоря о больших маршрутах и заблудиться там, у нас есть одна команда-ремесленник, которая помогает найти определенный маршрут.
Вы, наверное, все знаете, что php artisan route:list выдаст вам все маршруты в проекте.
Но знаете ли вы, что у вас есть больше возможностей фильтрации, чтобы найти именно то, что вы хотите? Просто добавьте --method, или --name, или --path с параметрами.
Фильтровать по методу — GET, POST и т. д.
Фильтровать по имени или части URL.
Это все, что я мог рассказать о группировке маршрутов в больших проектах. У вас есть другие примеры? Пожалуйста, поделитесь в комментариях.