Простейшая маршрутизация
В Laravel простейшие маршруты принимают URI (путь) и функцию-замыкание, предоставляя очень простой и выразительный метод определения маршрутов:
добавлено в 5.3 ()
Все маршруты (routes) Laravel определены в файлах маршрутов, которые расположены в каталоге routes. Эти файлы автоматически загружаются фреймворком. В файле routes/web.php определены маршруты для вашего web-интерфейса. Эти маршруты входят в группу посредников web, которые обеспечивают такие возможности, как состояние сессии и CSRF-защита. Маршруты из файла routes/api.php не поддерживают состояния и входят в группу посредников api.
Для большинства приложений сначала определяются маршруты в файле routes/web.php.
добавлено в 5.2 ()
Доступные методы маршрутизатора
Маршрутизатор позволяет регистрировать маршруты для любого 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-запросы нескольких типов. Это можно сделать методом PHPmatch()
. Или вы можете зарегистрировать маршрут, отвечающий на HTTP-запросы всех типов, с помощью метода PHPany()
:
Route::match(['get', 'post'], '/', function () {
//
});
Route::any('foo', function () {
//
});
Route::get('/', function () {
return 'Hello World';
});
Route::post('foo/bar', function () {
return 'Hello World';
});
Route::put('foo/bar', function () {
//
});
Route::delete('foo/bar', function () {
//
});
Регистрация маршрута для нескольких типов запросов
Иногда необходимо зарегистрировать маршрут, который отвечает на HTTP-запросы нескольких типов. Это можно сделать методом PHPmatch()
фасада Route:
Route::match(['get', 'post'], '/', function () {
return 'Hello World';
});
Или вы можете зарегистрировать маршрут, отвечающий на HTTP-запросы всех типов, с помощью метода PHPany()
:
Route::any('foo', function () {
return 'Hello World';
});
Генерирование адресов URL для маршрутов
Вы можете генерировать URL для маршрутов вашего приложения методом PHPurl()
:
$url = url('foo');
добавлено в 5.3 ()
Все 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;
});
Ограничения регулярными выражениями
Вы можете ограничить формат параметров вашего маршрута с помощью метода PHPwhere()
на экземпляре маршрута. Метод PHPwhere()
принимает название параметра и регулярное выражение, определяющее ограничения для параметра:
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]+']);
Если вы хотите, чтобы параметр был всегда ограничен заданным регулярным выражением, то можете использовать метод PHPpattern()
. Вам следует определить эти шаблоны в методе PHPboot()
вашего RouteServiceProvider:
добавлено в 5.3 ()
/**
* Определение привязок вашей модели, шаблонов фильтрации и т.д.
*
* @return void
*/
public function boot()
{
Route::pattern('id', '[0-9]+');
parent::boot();
}
добавлено в 5.2 () 5.1 () 5.0 ()
/**
* Определение привязок вашей модели, шаблонов фильтрации и т.д.
*
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function boot(Router $router)
{
$router->pattern('id', '[0-9]+');
parent::boot($router);
}
Когда шаблон определён, он автоматически применяется ко всем маршрутам, использующим этот параметр:
Route::get('user/{id}', function ($id) {
// Выполняется только если {id} числовой.
});
добавлено в 5.0 ()
Доступ к значению параметра маршрута
Если вам нужен доступ к значению параметра маршрута извне, то вы можете использовать метод PHPinput()
:
if ($route->input('id') == 1)
{
//
}
Также вы можете получить параметры текущего маршрута через экземпляр Illuminate\Http\Request. Получить объект текущего запроса можно через фасад Request или указав тип Illuminate\Http\Request, в котором внедрены зависимости:
use Illuminate\Http\Request;
Route::get('user/{id}', function(Request $request, $id)
{
if ($request->route('id'))
{
//
}
});
Именованные маршруты
Именованные маршруты позволяют удобно генерировать URL-адреса и делать переадресацию на конкретный маршрут.
добавлено в 5.3 ()
Также можно указать имена маршрутов для действий контроллера:
Route::get('user/profile', 'UserController@showProfile')->name('profile');
добавлено в 5.2 () 5.1 () 5.0 ()
Также можно указать имена маршрутов для действий контроллера:
Route::get('user/profile', [
'as' => 'profile', 'uses' => 'UserController@showProfile'
]);
Или, вместо указания имени маршрута в определении массива маршрутов вы можете «прицепить» метод PHPname()
к определению маршрута:
Route::get('user/profile', 'UserController@showProfile')->name('profile');
Группы маршрутов и именованные маршруты
Если вы используете группы маршрутов, то можете использовать ключ PHPas
в массиве атрибутов группы маршрутов, так вы можете задать общий префикс для имён маршрутов в группе:
Route::group(['as' => 'admin::'], function () {
Route::get('dashboard', ['as' => 'dashboard', function () {
// Маршрут назван "admin::dashboard"
}]);
});
добавлено в 5.0 ()
Генерирование URL адресов для именованных маршрутов
Когда вы назначили имя маршруту, вы можете использовать это имя для генерирования URL адресов и переадресаций глобальным методом PHProute()
:
// Генерирование URL...
$url = route('profile');
// Генерирование переадресаций...
return redirect()->route('profile');
Если у именованного маршрута есть параметры, вы можете передать их вторым аргументом метода PHProute()
. Эти параметры будут автоматически вставлены в соответствующие места URL:
Route::get('user/{id}/profile', function ($id) {
//
})->name('profile');
$url = route('profile', ['id' => 1]);
Группы маршрутов
Группы маршрутов позволяют использовать общие атрибуты маршрутов, такие как посредники и пространства имён, для большого числа маршрутов без необходимости определять эти атрибуты для каждого отдельного маршрута. Общие атрибуты указываются в виде массива первым аргументом метода PHPRoute::group()
.
Посредники
Посредники применяются ко всем маршрутам в группе путём указания списка этих посредников с параметром middleware в массиве групповых атрибутов. Посредники выполняются в порядке перечисления в этом массиве:
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Использует посредника Auth
});
Route::get('user/profile', function () {
// Использует посредника Auth
});
});
Пространства имён
Другой типичный пример использования групп маршрутов — назначение одного пространства имён PHP для группы контроллеров, используя параметр namespace в массиве группы:
Route::group(['namespace' => 'Admin'], function() {
// Контроллеры в пространстве имён "App\Http\Controllers\Admin"
//для версии 5.2 и ранее:
Route::group(['namespace' => 'User'], function() {
// Контроллеры в пространстве имён "App\Http\Controllers\Admin\User"
});
});
Помните, по умолчанию RouteServiceProvider включает ваши файлы маршрутов в группу пространства имён, позволяя вам регистрировать маршруты контроллера без указания полного префикса пространства имён App\Http\Controllers. Поэтому нам надо указать лишь ту часть пространства имён, которая следует за базовым пространством имён App\Http\Controllers.
Доменная маршрутизация
Группы маршрутов можно использовать для обработки маршрутизации поддоменов. Поддоменам можно назначать параметры маршрутов также как URI маршрутов, поэтому вы можете захватить часть поддомена и использовать в своём маршруте или контроллере. Поддомен можно указать с помощью ключа domain в массиве атрибутов группы:
Route::group(['domain' => '{account}.myapp.com'], function () {
Route::get('user/{id}', function ($account, $id) {
//
});
});
Префиксы маршрута
Атрибут группы prefix можно использовать для указания URI-префикса каждого маршрута в группе. Например, если вы хотите добавить admin ко всем URI маршрутов в группе:
Route::group(['prefix' => 'admin'], function () {
Route::get('users', function () {
// Соответствует URL "/admin/users"
});
});
добавлено в 5.0 ()
CSRF-защита
Данный раздел актуален для версии 5.2 и ранее. В версии 5.3 он был перенесён в отдельную статью о CSRF.
Введение
В Laravel легко защитить ваше приложение от CSRF-атаки межсайтовой подделки запросов. Межсайтовая подделка запроса — тип вредоносных атак, при котором неавторизованные команды выполняются от имени авторизованного пользователя.
Laravel автоматически генерирует CSRF-"токен" для каждой активной сессии пользователя в приложении. Этот токен используется для проверки того, что запрос в приложение отправляет именно авторизованный пользователь.
Каждый раз определяя HTML-форму в своём приложении, вы должны включать в неё скрытое поле CSRF-токена, чтобы посредник CSRF-защиты смог проверить запрос. Чтобы сгенерировать скрытое поле ввода _token, содержащее CSRF-токен, используйте вспомогательную функцию PHPcsrf_field()
:
// Vanilla PHP
<?php echo csrf_field(); ?>
// Blade Template Syntax
{{ csrf_field() }}
Функция PHPcsrf_field()
генерирует такой HTML:
xml<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
Вам не нужно вручную проверять CSRF-токен в запросах типа POST, PUT или DELETE. посредник VerifyCsrfToken, который входит в группу посредников web, будет автоматически проверять совпадение токена входящего запроса с токеном, хранящимся в сессии.
Исключение URI из CSRF-защиты
Иногда бывает необходимо исключить набор URI из CSRF-защиты. Например, при использовании Stripe для обработки платежей и их системы веб-хуков вам необходимо исключить ваш маршрут обработчика веб-хуков из CSRF-защиты Laravel.
Вы можете исключить URI, определив их маршруты вне группы посредников web, которая включена в файл по умолчанию routes.php, или добавив эти URI в свойство PHP$except
посредника VerifyCsrfToken:
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier
{
/**
* URI, которые надо исключить из проверки CSRF.
*
* @var array
*/
protected $except = [
'stripe/*',
];
}
X-CSRF-TOKEN
Кроме поиска CSRF-ключа в параметрах «POST», посредник VerifyCsrfToken также проверит наличие заголовка запроса X-CSRF-TOKEN. Например, вы можете хранить ключ в теге «meta»:
<meta name="csrf-token" content="{{ csrf_token() }}">
Когда вы создали тег meta, вы можете добавлять токен в заголовки всех запросов с помощью библиотеки, такой как jQuery. Так обеспечивается простая и удобная CSRF-защита для ваших приложений на основе AJAX:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
X-XSRF-TOKEN
Laravel также хранит CSRF-ключ в cookie XSRF-TOKEN. Вы можете использовать значение из cookie, чтобы задать заголовок запроса X-XSRF-TOKEN. Некоторые фреймворки JavaScript, такие как Angular, делают это автоматически. Вряд ли вам придётся использовать это значение вручную.
Разница между X-CSRF-TOKEN и X-XSRF-TOKEN в том, что первый использует простое текстовое значение, а второй — шифрованное значение, т.к. cookie в Laravel всегда шифруются. Если для передачи значения ключа вы используете функцию PHPcsrf_token()
, то вам вероятно нужно использовать заголовок X-CSRF-TOKEN.
Привязка модели
При внедрении ID модели в действие маршрута или контроллера бывает часто необходимо получить модель, соответствующую этому ID. Привязка моделей — удобный способ автоматического внедрения экземпляров модели напрямую в ваши маршруты. Например, вместо внедрения ID пользователя вы можете внедрить весь экземпляр модели User, который соответствует данному ID.
Неявная привязка
Laravel автоматически включает модели Eloquent, определённые в действиях маршрута или контроллера, чьи переменные имеют имена, совпадающие с сегментом маршрута. Например:
Route::get('api/users/{user}', function (App\User $user) {
return $user->email;
});
В этом примере Laravel автоматически внедрит экземпляр модели, который имеет ID, совпадающий с соответствующим значением из URI запроса, потому что переменная Eloquent PHP$user
, определённая в маршруте, совпадает с сегментом URI маршрута {user}. Если совпадающий экземпляр модели не найден в базе данных, будет автоматически сгенерирован HTTP-отклик 404.
Если вы хотите, чтобы для получения класса данной модели вместо столбца id использовался другой столбец базы данных, вы можете переопределить метод PHPgetRouteKeyName()
в своей модели Eloquent:
/**
* Получить ключ маршрута для модели.
*
* @return string
*/
public function getRouteKeyName()
{
return 'slug';
}
Явная привязка
Для регистрации явной привязки используйте метод маршрута PHPmodel()
для указания класса для данного параметра. Вам надо определить явные привязки вашей модели в методе PHPboot()
класса RouteServiceProvider:
добавлено в 5.3 ()
public function boot()
{
parent::boot();
Route::model('user', App\User::class);
}
добавлено в 5.2 () 5.1 () 5.0 ()
public function boot(Router $router)
{
parent::boot($router);
$router->model('user', 'App\User');
}
Затем определите маршрут, содержащий параметр PHP{user}
:
Route::get('profile/{user}', function (App\User $user) {
//
});
Из-за того, что мы ранее привязали все параметры PHP{user}
к модели App\User, её экземпляр будет внедрён в маршрут. Таким образом, к примеру, запрос profile/1 внедрит объект User, полученный из БД, который соответствует ID 1.
Если совпадающий экземпляр модели не найден в базе данных, будет автоматически сгенерирован HTTP-отклик 404.
Изменение логики принятия решения
добавлено в 5.3 ()
Если захотите использовать собственную логику принятия решения, используйте метод PHPRoute::bind()
. Переданное в метод PHPbind()
замыкание получит значение сегмента URI, и должно вернуть экземпляр класса, который вы хотите внедрить в маршрут:
public function boot()
{
parent::boot();
Route::bind('user', function ($value) {
return App\User::where('name', $value)->first();
});
}
добавлено в 5.2 ()
$router->bind('user', function ($value) {
return App\User::where('name', $value)->first();
});
добавлено в 5.0 ()
Route::model('user', 'User', function()
{
throw new NotFoundHttpException;
});
Route::bind('user', function($value)
{
return User::where('name', $value)->first();
});
Подмена методов
HTML-формы не поддерживают действия PUT, PATCH и DELETE. Поэтому при определении маршрутов PUT, PATCH и DELETE, вызываемых из HTML-формы, вам надо добавить в неё скрытое поле _method. Переданное в этом поле значение будет использовано как метод HTTP-запроса:
xml<form action="/foo/bar" method="POST"> <input type="hidden" name="_method" value="PUT"> <input type="hidden" name="_token" value="{{ csrf_token() }}"> </form>
Используйте вспомогательный метод PHPmethod_field()
, чтобы сгенерировать скрытое поле для _method:
{{ method_field('PUT') }}
Получение текущего маршрута
добавлено в 5.3 ()
добавлено в 5.2 ()
Метод PHPRoute::current()
вернёт маршрут, обрабатывающий текущий HTTP-запрос, позволяя вам проверить весь экземпляр Illuminate\Routing\Route:
$route = Route::current();
$name = $route->getName();
$actionName = $route->getActionName();
Также вы можете использовать вспомогательные методы PHPcurrentRouteName()
и PHPcurrentRouteAction()
фасада Route, чтобы получить имя или действие текущего маршрута:
$name = Route::currentRouteName();
$action = Route::currentRouteAction();
Чтобы изучить все доступные методы, обратитесь к документации по API класса, лежащего в основе фасада Route, и экземпляра Route.
Ошибки 404
Есть два способа вручную вызвать исключение 404 (Not Found) из маршрута. Первый — методом PHPabort()
, который просто вызывает Symfony\Component\HttpFoundation\Exception\HttpException с указанным кодом состояния:
abort(404);
Второй — вручную вызвав экземпляр Symfony\Component\HttpKernel\Exception\NotFoundHttpException.
Больше информации о том, как обрабатывать исключения 404 и отправлять собственный ответ для таких ошибок, вы найдёте в разделе об ошибках.
Комментарии (10)
Как сделать простое разветвление?
Если первая часть маршрута такая — то...
Всё остальное — так...
P.S. На форуме нашёл: https://laravel.ru/forum/viewtopic.php?id=1079
маршруты срабатывают в порядке их описания в routes.php
Через Префикс маршрута.
А как вывести маршруты, если они хранятся в бд? В бд есть путь и имя класса который должен подключаться.
а вы не пробовали переводить не своими словами, а используя общепринятые термины
— Регистрация маршрута для нескольких типов запросов
+ Регистрация маршрута для нескольких HTTP-методов запросов
В этом примере Laravel автоматически внедрит экземпляр модели, который имеет ID, совпадающий с соответствующим значением из URI запроса, потому что переменная Eloquent $user ...
..... хм кажется это называется объектом (модели), а не экземпляр модели, так будет всем понятно)))
Почему глобальные функции называют здесь методами?
Не стоило переводить HTML-элемент input на русский
Полезно, спасибо.
Хорошая статья! Спасибо.
Хорошая документация. Я ее законспектировал.