Любите загадки? Событие еще доступно на сайте.
Поддержите нас - каждый вклад важен!
Поддержите нас - каждый вклад важен!

Роутинг

Простейший роутинг

В Laravel простейшие роуты принимают URI (путь) и функцию-замыкание, предоставляя очень простой и выразительный метод определения роутов:

Route::get('foo', function () {
    return 'Hello World';
});

Файлы роутов по умолчанию

Все роуты Laravel определены в файлах роутов, которые расположены в директории routes. Эти файлы автоматически загружаются фреймворком. В файле routes/web.php определены роуты для вашего web-интерфейса. Эти роуты входят в группу посредников web, которые обеспечивают такие возможности, как состояние сессии и CSRF-защита. Роуты из файла routes/api.php не сохраняют состояние приложения и входят в группу посредников api.

Для большинства приложений сначала определяются роуты в файле routes/web.php.

Доступные методы роутера

Роутер (маршрутизатор) позволяет регистрировать роуты для любого HTTP-запроса:

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

Иногда необходимо зарегистрировать роут, который отвечает на HTTP-запросы нескольких типов. Это можно сделать методом match. Или вы можете зарегистрировать роут, отвечающий на HTTP-запросы всех типов, с помощью метода any:

Route::match(['get', 'post'], '/', function () {
    //
});

Route::any('foo', function () {
    //
});

CSRF-защита

Все HTML-формы, ведущие к роутам POST, PUT или DELETE, которые определены в файле роутов web , должны иметь поле CSRF-токена. Иначе запрос будет отклонён. Подробнее о CSRF-защите читайте в документации CSRF:

<form method="POST" action="/profile">
    {{ csrf_field() }}
    ...
</form>

Параметры роутов

Обязательные параметры

Разумеется, иногда вам может понадобиться захватить сегменты URI в вашем роуте. Например, если вам необходимо захватить ID пользователя из URL. Это можно сделать, определив параметры роута:

Route::get('user/{id}', function ($id) {
    return 'User '.$id;
});

Вы можете определить сколько угодно параметров:

Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
    //
});

Параметры роута всегда заключаются в фигурные скобки {} и должны состоять из буквенных символов. Параметры роута не могут содержать символ -. Используйте вместо него подчёркивание (_). Параметры роута внедряются в анонимные функции / контроллеры роута, основываясь на их порядке – названия аргументов анонимных функций / контроллеров не имеют значения.

Необязательные параметры

Иногда необходимо указать параметр роута, но при этом сделать его наличие необязательным. Это можно сделать, поместив знак вопроса ? после названия параметра. Не забудьте задать значение по умолчанию для соответствующей переменной роута:

Route::get('user/{name?}', function ($name = null) {
    return $name;
});

Route::get('user/{name?}', function ($name = 'John') {
    return $name;
});

Ограничения регулярными выражениями

Вы можете ограничить формат параметров вашего роута с помощью метода where на экземпляре роута. Метод where принимает название параметра и регулярное выражение, определяющее ограничения для параметра:

Route::get('user/{name}', function ($name) {
    //
})->where('name', '[A-Za-z]+');

Route::get('user/{id}', function ($id) {
    //
})->where('id', '[0-9]+');

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

Глобальные ограничения

Если вы хотите, чтобы параметр был всегда ограничен заданным регулярным выражением, то можете использовать метод pattern. Вам следует определить эти шаблоны в методе boot вашего RouteServiceProvider:

/**
 * Define your route model bindings, pattern filters, etc.
 *
 * @return void
 */
public function boot()
{
    Route::pattern('id', '[0-9]+');

    parent::boot();
}

Когда шаблон был определён, он автоматически применится ко всем роутам, использующим этот параметр:

Route::get('user/{id}', function ($id) {
    // Only executed if {id} is numeric...
});

Именованные роуты

Именованные роуты позволяют удобно генерировать URL-адреса и делать переадресацию на конкретный роут. Вы можете задать имя роута, прицепив метод name к определению роута:

Route::get('user/profile', function () {
    //
})->name('profile');

Также можно указать имена роутов для действий контроллера:

Route::get('user/profile', 'UserController@showProfile')->name('profile');

Генерирование URL адресов для именованных роутов

Когда вы назначили имя роуту, вы можете использовать это имя для генерирования URL адресов и переадресаций глобальным методом route:

// Generating URLs...
$url = route('profile');

// Generating Redirects...
return redirect()->route('profile');

Если у именованного роута есть параметры, вы можете передать их вторым аргументом метода route. Эти параметры будут автоматически вставлены в соответствующие места URL:

Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1]);

Группы роутов

Группы роутов позволяют использовать общие атрибуты роутов, такие как посредники и пространства имён, для большого числа роутов без необходимости определять эти атрибуты для каждого отдельного роута. Общие атрибуты указываются в виде массива первым аргументом метода Route::group.

Посредники

Посредники применяются ко всем роутам в группе путём указания списка этих посредников с параметром middleware в массиве групповых атрибутов. Посредники выполняются в порядке перечисления в этом массиве:

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // Uses first & second Middleware
    });

    Route::get('user/profile', function () {
        // Uses first & second Middleware
    });
});

Пространства имён

Другой типичный пример использования групп роутов — назначение одного пространства имён PHP для группы контроллеров, используя параметр namespace в массиве группы:

Route::namespace('Admin')->group(function () {
    // Controllers Within The "App\Http\Controllers\Admin" Namespace
});

Помните, по умолчанию RouteServiceProvider включает ваши файлы роутов в группу пространства имён, позволяя вам регистрировать роуты контроллера без указания полного префикса пространства имён App\Http\Controllers. Поэтому нам надо указать лишь ту часть пространства имён, которая следует за базовым пространством имён App\Http\Controllers.

Доменный роутинг

Группы роутов можно использовать для обработки маршрутизации поддоменов. Поддоменам можно назначать параметры роутов также как URI роутов, поэтому вы можете захватить часть поддомена и использовать в своём роуте или контроллере. Поддомен можно указать с помощью ключа domain в массиве атрибутов группы:

Route::domain('{account}.myapp.com')->group(function () {
    Route::get('user/{id}', function ($account, $id) {
        //
    });
});

Префиксы роута

Метод prefix можно использовать для указания URI-префикса каждого роута в группе. Например, если вы хотите добавить admin ко всем URI роутов в группе:

Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // Matches The "/admin/users" URL
    });
});

Привязка модели роута

При внедрении ID модели в действие роута или контроллера бывает часто необходимо получить модель, соответствующую этому ID. Привязка моделей — удобный способ автоматического внедрения экземпляров модели напрямую в ваши роуты. Например, вместо внедрения ID пользователя вы можете внедрить весь экземпляр модели User, который соответствует данному ID.

Неявная привязка

Laravel автоматически включает модели Eloquent, определённые в действиях роута или контроллера, чьи переменные имеют имена, совпадающие с сегментом роута. Например:

Route::get('api/users/{user}', function (App\User $user) {
    return $user->email;
});

Так как переменная $user указывается в качестве аргумента Eloquent модели App\User и название переменной совпадает с URI-сегментом {user}, автоматически внедрит экземпляр модели, который имеет ID, совпадающий с соответствующим значением из URI запроса. Если совпадающий экземпляр модели не найден в базе данных, будет автоматически сгенерирован HTTP-отклик 404.

Изменение имени ключа

Если вы хотите, чтобы для получения класса данной модели вместо столбца id использовался другой столбец базы данных, вы можете переопределить метод getRouteKeyName в своей модели Eloquent:

/**
 * Get the route key for the model.
 *
 * @return string
 */
public function getRouteKeyName()
{
    return 'slug';
}

Явная привязка

Для регистрации явной привязки используйте метод роута model для указания класса для данного параметра. Вам надо определить явные привязки вашей модели в методе boot класса RouteServiceProvider:

public function boot()
{
    parent::boot();

    Route::model('user', App\User::class);
}

Затем определите роут, содержащий параметр {user}:

Route::get('profile/{user}', function (App\User $user) {
    //
});

Из-за того, что мы ранее привязали все параметры {user} к модели App\User, её экземпляр будет внедрён в роут. Таким образом, к примеру, запрос profile/1 внедрит объект User , полученный из БД, который соответствует ID 1.

Если совпадающий экземпляр модели не найден в базе данных, будет автоматически сгенерирован HTTP-отклик 404.

Изменение логики принятия решения

Если захотите использовать собственную логику принятия решения, используйте метод Route::bind . Переданное в метод bind замыкание получит значение сегмента URI, и должно вернуть экземпляр класса, который вы хотите внедрить в роут:

public function boot()
{
    parent::boot();

    Route::bind('user', function ($value) {
        return App\User::where('name', $value)->first();
    });
}

Подмена методов

HTML-формы не поддерживают действия PUT, PATCH или DELETE. Поэтому при определении роутов PUT, PATCH или DELETE, вызываемых из HTML-формы, вам надо добавить в неё скрытое поле _method. Переданное в этом поле значение будет использовано как метод HTTP-запроса:

<form action="/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>

Используйте хелпер method_field, чтобы сгенерировать ввод _method:

{{ method_field('PUT') }}

Получение текущего роута

Используйте методы current, currentRouteName и currentRouteAction фасада Route для получения информации о роуте, обрабатывающем входящий запрос:

$route = Route::current();

$name = Route::currentRouteName();

$action = Route::currentRouteAction();

Чтобы изучить все доступные методы, обратитесь к документации по API класса, лежащего в основе фасада Route и экземпляра Route.