Именованные маршруты 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 шт):

Автор решения: mydls1

Когда вы определяете группу маршрутов с префиксом 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 сгенерирует уникальное имя и объединит его с префиксом.
→ Ссылка