Может войдёшь?
Черновики Написать статью Профиль

Маршрутизация

перевод документация 5.х

  1. 1. Простейшая маршрутизация
  2. 2. Параметры маршрутов
    1. 2.1. Обязательные параметры
    2. 2.2. Необязательные параметры маршрута
    3. 2.3. Ограничения регулярными выражениями
  3. 3. Именованные маршруты
  4. 4. Группы маршрутов
    1. 4.1. Посредники
    2. 4.2. Пространства имён
    3. 4.3. Доменная маршрутизация
    4. 4.4. Префиксы маршрута
  5. 5. CSRF-защита
    1. 5.1. Введение
    2. 5.2. Исключение URI из CSRF-защиты
    3. 5.3. X-CSRF-TOKEN
    4. 5.4. X-XSRF-TOKEN
  6. 6. Привязка модели
    1. 6.1. Неявная привязка
    2. 6.2. Явная привязка
  7. 7. Подмена методов
  8. 8. Получение текущего маршрута
  9. 9. Ошибки 404
Этот перевод актуален для англоязычной документации на (ветка 5.3) , (ветка 5.2) , (ветка 5.1) и (ветка 5.0). Опечатка? Выдели и нажми Ctrl+Enter.

Простейшая маршрутизация

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

+ 5.3 5.2

добавлено в 5.3 () 5.2 ()

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

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

+ 5.3

добавлено в 5.3 ()

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

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

+ 5.2

добавлено в 5.2 ()

Файл routes.php загружается провайдером RouteServiceProvider и автоматически включается в группу посредников web, что обеспечивает доступ к состоянию сессии и CSRF-защиту. Большинство маршрутов вашего приложения будут определены в этом файле.

+ 5.3 5.2

добавлено в 5.3 () 5.2 ()

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

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

PHP
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():

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

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

добавлено в 5.1 () 5.0 ()

PHP
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:

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

Или вы можете зарегистрировать маршрут, отвечающий на HTTP-запросы всех типов, с помощью метода PHPany():

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

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

Вы можете генерировать URL для маршрутов вашего приложения методом PHPurl():

PHP
$url url('foo');
+ 5.3

добавлено в 5.3 ()

CSRF-защита

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

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

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

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

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

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

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

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

Параметры маршрута всегда заключаются в фигурные скобки и должны состоять из буквенных символов. Параметры маршрута не могут содержать символ -. Используйте вместо него подчёркивание _.

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

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

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

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

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

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

PHP
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

добавлено в 5.3 ()

PHP
/**
 * Определение привязок вашей модели, шаблонов фильтрации и т.д.
 *
 * @return void
 */
public function boot()
{
  
Route::pattern('id''[0-9]+');

  
parent::boot();
}
+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

PHP
/**
 * Определение привязок вашей модели, шаблонов фильтрации и т.д.
 *
 * @param  \Illuminate\Routing\Router  $router
 * @return void
 */
public function boot(Router $router)
{
  
$router->pattern('id''[0-9]+');

  
parent::boot($router);
}

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

PHP
Route::get('user/{id}', function ($id) {
  
// Выполняется только если {id} числовой.
});
+ 5.0

добавлено в 5.0 ()

Доступ к значению параметра маршрута

Если вам нужен доступ к значению параметра маршрута извне, то вы можете использовать метод PHPinput():

PHP
if ($route->input('id') == 1)
{
  
//
}

Также вы можете получить параметры текущего маршрута через экземпляр Illuminate\Http\Request. Получить объект текущего запроса можно через фасад Request или указав тип Illuminate\Http\Request, в котором внедрены зависимости:

PHP
use Illuminate\Http\Request;

Route::get('user/{id}', function(Request $request$id)
{
  if (
$request->route('id'))
  {
    
//
  
}
});

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

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

+ 5.3

добавлено в 5.3 ()

Вы можете задать имя маршрута, прицепив метод PHPname() к определению маршрута:

PHP
Route::get('user/profile', function () {
  
//
})->name('profile');
+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

Вы можете задать имя маршрута с помощью ключа массива PHPas:

PHP
Route::get('user/profile', ['as' => 'profile', function () {
  
//
}]);

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

PHP
Route::get('user/profile''UserController@showProfile')->name('profile');
+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

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

PHP
Route::get('user/profile', [
  
'as' => 'profile''uses' => 'UserController@showProfile'
]);

Или, вместо указания имени маршрута в определении массива маршрутов вы можете «прицепить» метод PHPname() к определению маршрута:

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

Группы маршрутов и именованные маршруты

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

PHP
Route::group(['as' => 'admin::'], function () {
  
Route::get('dashboard', ['as' => 'dashboard', function () {
    
// Маршрут назван "admin::dashboard"
  
}]);
});
+ 5.0

добавлено в 5.0 ()

Метод PHPcurrentRouteName() возвращает имя маршрута, обрабатывающего текущий запрос:

PHP
$name Route::currentRouteName();

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

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

PHP
// Генерирование URL...
$url route('profile');

// Генерирование переадресаций...
return redirect()->route('profile');

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

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

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

Группы маршрутов

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

Посредники

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

PHP
Route::group(['middleware' => 'auth'], function () {
  
Route::get('/', function ()    {
    
// Использует посредника Auth
  
});

  
Route::get('user/profile', function () {
    
// Использует посредника Auth
  
});
});

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

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

PHP
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 в массиве атрибутов группы:

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

Префиксы маршрута

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

PHP
Route::group(['prefix' => 'admin'], function () {
  
Route::get('users', function ()    {
    
// Соответствует URL "/admin/users"
  
});
});
+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

Вы также можете использовать параметр prefix для передачи общих параметров в ваши сгруппированные маршруты:

PHP
Route::group(['prefix' => 'accounts/{account_id}'], function () {
  
Route::get('detail', function ($accountId)    {
    
// Соответствует URL "accounts/{account_id}/detail"
  
});
});
+ 5.0

добавлено в 5.0 ()

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

PHP
Route::group([
  
'prefix' => 'accounts/{account_id}',
  
'where' => ['account_id' => '[0-9]+'],
], function() {

  
// Здесь определение маршрутов
});

CSRF-защита

Данный раздел актуален для версии 5.2 и ранее. В версии 5.3 он был перенесён в отдельную статью о CSRF.

Введение

В Laravel легко защитить ваше приложение от CSRF-атаки межсайтовой подделки запросов. Межсайтовая подделка запроса — тип вредоносных атак, при котором неавторизованные команды выполняются от имени авторизованного пользователя.

Laravel автоматически генерирует CSRF-"токен" для каждой активной сессии пользователя в приложении. Этот токен используется для проверки того, что запрос в приложение отправляет именно авторизованный пользователь.

Каждый раз определяя HTML-форму в своём приложении, вы должны включать в неё скрытое поле CSRF-токена, чтобы посредник CSRF-защиты смог проверить запрос. Чтобы сгенерировать скрытое поле ввода _token, содержащее CSRF-токен, используйте вспомогательную функцию PHPcsrf_field():

PHP
// 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
<?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»:

PHP
<meta name="csrf-token" content="{{ csrf_token() }}">

Когда вы создали тег meta, вы можете добавлять токен в заголовки всех запросов с помощью библиотеки, такой как jQuery. Так обеспечивается простая и удобная CSRF-защита для ваших приложений на основе AJAX:

PHP
$.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.

+ 5.3 5.2

добавлено в 5.3 () 5.2 ()

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

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

PHP
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:

PHP
/**
 * Получить ключ маршрута для модели.
 *
 * @return string
 */
public function getRouteKeyName()
{
  return 
'slug';
}

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

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

+ 5.3

добавлено в 5.3 ()

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

  
Route::model('user'App\User::class);
}
+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

PHP
public function boot(Router $router)
{
  
parent::boot($router);

  
$router->model('user''App\User');
}

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

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

добавлено в 5.0 ()

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

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

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

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

+ 5.3

добавлено в 5.3 ()

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

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

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

добавлено в 5.2 ()

PHP
$router->bind('user', function ($value) {
  return 
App\User::where('name'$value)->first();
});
+ 5.2 5.1

добавлено в 5.2 () 5.1 ()

Изменение поведения при событии «не найдено»

Если вы хотите задать свой собственный обработчик для события «не найдено», вы можете передать функцию-замыкание в качестве третьего аргумента метода PHPmodel():

PHP
$router->model('user''App\User', function() {
  throw new 
NotFoundHttpException;
});
+ 5.0

добавлено в 5.0 ()

PHP
Route::model('user''User', function()
{
  throw new 
NotFoundHttpException;
});
PHP
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>
+ 5.2 5.1 5.0

добавлено в 5.2 () 5.1 () 5.0 ()

Для создания скрытого поля _method вы также можете использовать функцию PHPmethod_field():

PHP
<?php echo method_field('PUT'); ?>

Используйте вспомогательный метод PHPmethod_field(), чтобы сгенерировать скрытое поле для _method:

PHP
{{ method_field('PUT') }}

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

+ 5.3

добавлено в 5.3 ()

Используйте методы PHPcurrent(), PHPcurrentRouteName() и PHPcurrentRouteAction() фасада Route для получения информации о маршруте, обрабатывающем входящий запрос:

PHP
$route Route::current();

$name Route::currentRouteName();

$action Route::currentRouteAction();
+ 5.2

добавлено в 5.2 ()

Метод PHPRoute::current() вернёт маршрут, обрабатывающий текущий HTTP-запрос, позволяя вам проверить весь экземпляр Illuminate\Routing\Route:

PHP
$route Route::current();

$name $route->getName();

$actionName $route->getActionName();

Также вы можете использовать вспомогательные методы PHPcurrentRouteName() и PHPcurrentRouteAction() фасада Route, чтобы получить имя или действие текущего маршрута:

PHP
$name Route::currentRouteName();
$action Route::currentRouteAction();

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

+ 5.1 5.0

добавлено в 5.1 () 5.0 ()

Ошибки 404

Есть два способа вручную вызвать исключение 404 (Not Found) из маршрута. Первый — методом PHPabort(), который просто вызывает Symfony\Component\HttpFoundation\Exception\HttpException с указанным кодом состояния:

PHP
abort(404);

Второй — вручную вызвав экземпляр Symfony\Component\HttpKernel\Exception\NotFoundHttpException.

Больше информации о том, как обрабатывать исключения 404 и отправлять собственный ответ для таких ошибок, вы найдёте в разделе об ошибках.

Комментарии (10)

Max_G

Как сделать простое разветвление?
Если первая часть маршрута такая — то...
Всё остальное — так...

P.S. На форуме нашёл: https://laravel.ru/forum/viewtopic.php?id=1079
маршруты срабатывают в порядке их описания в routes.php

Phizio

Через Префикс маршрута.

// Групповая декларация всех вариантов, начинающихся с first
Route::group(['prefix' => 'first'], function()
{
  Route::get('second1', function()
  {
    // Соответствует URL "/first/second1"
  });
  Route::get('second2', function()
  {
    // Соответствует URL "/first/second2"
  });
  // итп... сколько угодно блоков для второй части маршрута
});

// Другие маршруты (не начинающиеся с first)
Route::get('profile/{user}', function(App\User $user)
{
  //
});
morozov

А как вывести маршруты, если они хранятся в бд? В бд есть путь и имя класса который должен подключаться.

qwerukg

а вы не пробовали переводить не своими словами, а используя общепринятые термины


— Регистрация маршрута для нескольких типов запросов
+ Регистрация маршрута для нескольких HTTP-методов запросов

blackdark20

В этом примере Laravel автоматически внедрит экземпляр модели, который имеет ID, совпадающий с соответствующим значением из URI запроса, потому что переменная Eloquent $user ...

..... хм кажется это называется объектом (модели), а не экземпляр модели, так будет всем понятно)))

andreykp

Почему глобальные функции называют здесь методами?

andreykp
  1. Используйте вспомогательный метод method_field(), чтобы сгенерировать ввод _method:

Не стоило переводить HTML-элемент input на русский

Kejum

Полезно, спасибо.

FominTimur

Хорошая статья! Спасибо.

AlekseyP

Хорошая документация. Я ее законспектировал.

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.