Именованные маршруты Laravel в чем разница?
Хотелось бы понять в чем разница т.к. ответа найти не смог.
Есть маршрут
Route::group([
'middleware' => ['api'],
], function () {
Route::prefix('api/verson')->name('api.version.')->group(function () {
Route::prefix('project')->name('project')->group(function () {
Route::get('worker', [NameController::class, 'worker']);
})
})
});
В списке маршрутов это выглядит вот так:
Method | URI | Name |
GET|HEAD | api/version/project/worker | api.version.project |
При попытке добавить еще один маршрут
Route::get('worker-list', [NameController::class, 'list']);
Появляется ошибка, что маршрут api.version.project уже добавлен. Т.е. получается name уже зарезервировано.
Однако, если маршруты будут выглядеть вот так
Route::group([
'middleware' => ['api'],
], function () {
Route::prefix('api/verson')->name('api.version.')->group(function () {
Route::prefix('project')->name('project.')->group(function () {
Route::get('worker', [NameController::class, 'worker']);
})
})
});
То новый маршрут добавиться без проблем и список роутов будет выглядеть вот так
Method | URI | Name |
GET|HEAD | api/version/project/worker |api.version.project. |
GET|HEAD | api/version/project/worker-list |api.version.project.generated::WIlQFglGb43vStI|
Кто не заметил был ->name('project')
стало ->name('project.')
хотелось бы понять в чем разница. Точка позволяет сгенерировать уникальный name на похожие маршруты?
Ответы (1 шт):
Когда вы определяете группу маршрутов с префиксом name, Laravel использует этот префикс для генерации имен маршрутов внутри группы. Вот как это работает:
Без точки ('project'):
Route::prefix('project')->name('project')->group(function () {
Route::get('worker', [NameController::class, 'worker']);
Route::get('worker-list', [NameController::class, 'list']);
});
В этом случае префикс имени — 'project' без точки в конце. Laravel пытается присвоить имя 'project' обоим маршрутам внутри группы. Это приводит к конфликту, поскольку имена маршрутов должны быть уникальными. Поэтому при попытке добавить второй маршрут вы получаете ошибку, сообщающую, что имя маршрута 'api.version.project' уже используется.
С точкой ('project.'):
Route::prefix('project')->name('project.')->group(function () {
Route::get('worker', [NameController::class, 'worker']);
Route::get('worker-list', [NameController::class, 'list']);
});
Добавляя точку в конце ('project.'), вы указываете Laravel, что 'project.' — это префикс для имен маршрутов, а не полное имя. Это позволяет Laravel добавлять уникальные суффиксы или подименования к каждому маршруту внутри группы. Если вы не указываете имя для отдельного маршрута, Laravel автоматически сгенерирует уникальное имя, чтобы избежать конфликтов.
protected $aliases = [
'name' => 'as',
'scopeBindings' => 'scope_bindings',
'withoutMiddleware' => 'excluded_middleware',
];
Вот метод (name это тот же as в атрибуте метода group)
/**
* Format the "as" clause of the new group attributes.
*
* @param array $new
* @param array $old
* @return array
*/
protected static function formatAs($new, $old)
{
if (isset($old['as'])) {
$new['as'] = $old['as'].($new['as'] ?? '');
}
return $new;
}
именно поэтому правильнее писать
Route::group(['prefix' => 'project', 'as' => 'project.'], function () {
Route::get('worker', [HomeController::class, 'index'])->name('worker');
});
Теперь вы поняли? Что если вы пишите без точки, то это имя присваивается к каждому дочернему элементу, а если с точкой, то вызывается генерация и создается уникальное имя.
Для большего понимания просмотрите
- Класс Illuminate\Routing\RouteRegistrar Метод attributeGroup объединяет атрибуты группы и маршрута. Параметр name из группы объединяется с параметром name из маршрута.
- Класс Illuminate\Routing\Route Метод name устанавливает имя маршрута, используя префикс из группы, если он есть. Если имя маршрута не указано, но есть префикс name из группы с точкой, Laravel сгенерирует уникальное имя и объединит его с префиксом.