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

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

перевод документация 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. Привязка модели
  7. 7. Подмена методов
  8. 8. Ошибки 404
Этот перевод актуален для англоязычной документации на (ветка 5.1) и (ветка 5.0). Опечатка? Выдели и нажми Ctrl+Enter.

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

Большинство маршрутов (routes) вашего приложения будут определены в файле app/Http/routes.php, который загружается классом App\Providers\RouteServiceProvider. В Laravel простейший маршрут принимает URI (путь) и функцию-замыкание:

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');

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

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

Разумеется, иногда вам может понадобиться захватить сегменты 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:

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-адреса и делать переадресацию на конкретный маршрут. Вы можете задать имя маршруту с помощью ключа массива PHPas:

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

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

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

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

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

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

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

PHP
$name Route::currentRouteName();

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

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

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

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

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

PHP
$url route('profile');

$redirect redirect()->route('profile');

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

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

$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"

  
Route::group(['namespace' => 'User'], function()
  {
    
// Контроллеры в пространстве имён "App\Http\Controllers\Admin\User"
  
});
});

Помните, по умолчанию RouteServiceProvider включает файл routes.php в группу пространства имён, позволяя вам регистрировать маршруты контроллера без указания полного префикса пространства имён 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"
  
});
});

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

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

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

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

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

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

CSRF-защита

Введение

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

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

PHP
<?php echo csrf_field(); ?>

Функция PHPcsrf_field() генерирует такой HTML:

xml<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">

И само собой, при использовании системы шаблонов Blade:

PHP
{{ csrf_field() }}

Вам не нужно вручную проверять CSRF-токен в запросах типа POST, PUT или DELETE. HTTP-посредник VerifyCsrfToken будет проверять совпадение токена входящего запроса с токеном, хранящимся в сессии.

Исключение URI из CSRF-защиты

Иногда бывает необходимо исключить набор URI из CSRF-защиты. Например, при использовании Stripe для обработки платежей и их системы веб-хуков вам необходимо исключить ваш маршрут обработчика веб-хуков из CSRF-защиты Laravel.

Вы можете исключить 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 пользователя вы можете внедрить весь экземпляр класса User, который соответствует данному ID.

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

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

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

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

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

PHP
$router->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 (полученному из БД — прим. пер.).

Если переданный ID не соответствует строке в БД, будет вызвано исключение 404.

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

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

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

PHP
Route::model('user''User', function()
{
  throw new 
NotFoundHttpException;
});

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

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

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

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>

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

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

Конечно, если вы используете шаблонизатор Blade:

PHP
{{ method_field('PUT') }}

Ошибки 404

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

PHP
abort(404);

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

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

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

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-методов запросов

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

Разметка: ? ?

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