Подписывайтесь на наш Telegram канал и будьте в курсе всех событий.
Ищете работу? Мы поможем!
Ищете работу? Мы поможем!

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

Основы маршрутизации

Простейшие маршруты Laravel принимают URI и замыкание, обеспечивая нетрудоемкий и выразительный метод определения маршрутов и поведения без сложных конфигурационных файлов маршрутизации:

use Illuminate\Support\Facades\Route;

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

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

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

Для большинства приложений вы начнете с определения маршрутов в файле routes/web.php. К маршрутам, определенным в routes/web.php, можно получить доступ, введя URL-адрес определенного маршрута в вашем браузере. Например, вы можете получить доступ к следующему маршруту, перейдя по адресу http://example.com/user в своем браузере:

use App\Http\Controllers\UserController;

Route::get('/user', [UserController::class, 'index']);

Маршруты API

Если ваше приложение также будет предлагать API без сохранения состояния, вы можете включить маршрутизацию API с помощью команды Artisan install:api:

php artisan install:api

Команда install:api устанавливает Laravel Sanctum, который обеспечивает надежную, но простую защиту аутентификации токена API, которую можно использовать для аутентификации сторонних потребителей API, SPA, или мобильных приложений. Кроме того, команда install:api создает файл routes/api.php:

Route::get('/user', function (Request $request) {
    return $request->user();
})->middleware('auth:sanctum');

Маршруты в routes/api.php не сохраняют состояние и назначаются api группе посредников. Кроме того, к этим маршрутам автоматически применяется префикс URI /api, поэтому вам не нужно вручную применять его к каждому маршруту в файле. Вы можете изменить префикс, изменив файл bootstrap/app.php вашего приложения:

->withRouting(
    api: __DIR__.'/../routes/api.php',
    apiPrefix: 'api/admin',
    // ...
)

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

Маршрутизатор позволяет регистрировать маршруты, отвечающие на любой 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('/', function () {
    // ...
});

При определении нескольких маршрутов, которые используют один и тот же URI, маршруты, использующие методы get, post, put, patch, delete и options, должны быть определены перед маршрутами, использующими методы any, match и redirect. Это гарантирует, что входящий запрос соответствует правильному маршруту.

Внедрение зависимости

Вы можете объявить любые зависимости, необходимые для вашего маршрута, в сигнатуре замыкания вашего маршрута. Объявленные зависимости будут автоматически извлечены и внедрены в замыкание с помощью контейнера служб Laravel. Например, вы можете объявить класс Illuminate\Http\Request, чтобы текущий HTTP-запрос автоматически был внедрен в замыкание вашего маршрута:

use Illuminate\Http\Request;

Route::get('/users', function (Request $request) {
    // ...
});

Защита от CSRF

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

<form method="POST" action="/profile">
    @csrf
    ...
</form>

Маршруты перенаправлений

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

Route::redirect('/here', '/there');

По умолчанию Route::redirect возвращает код состояния 302. Вы можете переопределить код состояния, используя необязательный третий параметр:

Route::redirect('/here', '/there', 301);

Или вы можете использовать метод Route::permanentRedirect для возврата кода состояния 301:

Route::permanentRedirect('/here', '/there');

При использовании параметров маршрута в маршрутах перенаправления, следующие параметры зарезервированы Laravel и не могут быть использованы: destination и status.

Маршруты представлений

Если ваш маршрут должен возвращать только HTML-шаблон, то вы можете использовать метод Route::view. Как и метод redirect, этот метод имеет лаконичную запись, так что вам не нужно полностью определять маршрут или контроллер. Метод view принимает URI в качестве первого аргумента и имя шаблона в качестве второго аргумента. Кроме того, вы можете указать массив данных для передачи в шаблон в качестве необязательного третьего аргумента:

Route::view('/welcome', 'welcome');

Route::view('/welcome', 'welcome', ['name' => 'Taylor']);

При использовании параметров маршрута в маршрутах представлений, следующие параметры зарезервированы Laravel и не могут быть использованы: view, data, status и headers.

Список ваших маршрутов

Команда Artisan route:list может легко предоставить обзор всех маршрутов, определенных вашим приложением:

php artisan route:list

По умолчанию промежуточное программное обеспечение маршрутов, назначенных каждому маршруту, не будет отображаться в выводе route:list; однако вы можете указать Laravel отображать промежуточное программное обеспечение маршрутов и имена групп промежуточного программного обеспечения, добавив опцию -v к команде:

php artisan route:list -v

# Расширить группы промежуточного программного обеспечения...
php artisan route:list -vv

Вы также можете указать Laravel показывать только маршруты, начинающиеся с указанного URI:

php artisan route:list --path=api

Кроме того, вы можете указать Laravel скрыть любые маршруты, определенные сторонними пакетами, предоставив опцию --except-vendor при выполнении команды route:list:

php artisan route:list --except-vendor

Также вы можете указать Laravel показывать только маршруты, определенные сторонними пакетами, предоставив опцию --only-vendor при выполнении команды route:list:

php artisan route:list --only-vendor

Настройка маршрутизации

По умолчанию маршруты вашего приложения настраиваются и загружаются в файле bootstrap/app.php:

<?php

use Illuminate\Foundation\Application;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )->create();

Однако иногда вам может потребоваться определить совершенно новый файл, содержащий подмножество маршрутов вашего приложения. Для этого вы можете предоставить замыкание then для метода withRouting. В рамках этого замыкания вы можете прописать любые дополнительные маршруты, необходимые для вашего приложения:

use Illuminate\Support\Facades\Route;

->withRouting(
    web: __DIR__.'/../routes/web.php',
    commands: __DIR__.'/../routes/console.php',
    health: '/up',
    then: function () {
        Route::middleware('api')
            ->prefix('webhooks')
            ->name('webhooks.')
            ->group(base_path('routes/webhooks.php'));
    },
)

Или вы можете даже получить полный контроль над регистрацией маршрута, предоставив замыкание using для метода withRouting. При передаче этого аргумента платформа не будет регистрировать HTTP-маршруты, и вы несете ответственность за регистрацию всех маршрутов вручную:

use Illuminate\Support\Facades\Route;

->withRouting(
    commands: __DIR__.'/../routes/console.php',
    using: function () {
        Route::middleware('api')
            ->prefix('api')
            ->group(base_path('routes/api.php'));

        Route::middleware('web')
            ->group(base_path('routes/web.php'));
    },
)

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

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

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

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

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

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

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

Параметры и внедрение зависимости

Если у вашего маршрута есть зависимости, которые вы хотите, чтобы контейнер служб Laravel автоматически внедрил в замыкание вашего маршрута, то вы должны указать эти зависимости перед параметрами маршрута:

use Illuminate\Http\Request;

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

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

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

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

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

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

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

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

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

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

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

Route::get('/user/{id}/{name}', function (string $id, string $name) {
    // ...
})->whereNumber('id')->whereAlpha('name');

Route::get('/user/{name}', function (string $name) {
    // ...
})->whereAlphaNumeric('name');

Route::get('/user/{id}', function (string $id) {
    // ...
})->whereUuid('id');

Route::get('/user/{id}', function (string $id) {
    // ...
})->whereUlid('id');

Route::get('/category/{category}', function (string $category) {
    // ...
})->whereIn('category', ['movie', 'song', 'painting']);

Route::get('/category/{category}', function (string $category) {
    // ...
})->whereIn('category', CategoryEnum::cases());

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

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

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

use Illuminate\Support\Facades\Route;

/**
 * Запуск любых служб приложения.
 */
public function boot(): void
{
    Route::pattern('id', '[0-9]+');
}

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

Route::get('/user/{id}', function (string $id) {
    // Выполнится, только если параметр `{id}` имеет числовое значение ...
});

Кодирование обратных слешей

Компонент маршрутизации Laravel позволяет всем символам, кроме обратного слеша (/), присутствовать в значениях параметров маршрута. Вы должны явно разрешить / быть частью заполнителя {}, используя регулярное выражение условия where:

Route::get('/search/{search}', function ($search) {
    return $search;
})->where('search', '.*');

Обратные слеши поддерживаются только в рамках последнего сегмента маршрута.

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

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

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

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

Route::get(
    '/user/profile',
    [UserProfileController::class, 'show']
)->name('profile');

Имена маршрутов всегда должны быть уникальными.

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

После того как вы присвоили имя указанному маршруту, вы можете использовать имя маршрута при генерации URL-адресов или перенаправлений с помощью вспомогательных глобальных функций route и redirect Laravel:

// Создание URL-адреса ...
$url = route('profile');

// Создание перенаправления ...
return redirect()->route('profile');

return to_route('profile');

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

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

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

Если вы передадите дополнительные параметры в массиве, то эти пары ключ / значение будут автоматически добавлены в строку запроса сгенерированного URL-адреса:

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

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

// /user/1/profile?photos=yes

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

Получение информации о текущем именованном маршруте

Если вы хотите определить, был ли текущий запрос направлен на конкретный именованный маршрут, то вы можете использовать метод named экземпляра Route. Например, вы можете проверить имя текущего маршрута из посредника маршрута:

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Обработка входящего запроса.
 * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
 */
public function handle(Request $request, Closure $next): Response
{
    if ($request->route()->named('profile')) {
        // ...
    }

    return $next($request);
}

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

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

Вложенные группы пытаются разумно «объединить» атрибуты со своей родительской группой. Посредники и условия where объединяются, а имена и префиксы добавляются. Разделители пространства имен и слеши в префиксах URI автоматически добавляются там, где это необходимо.

Посредники

Чтобы назначить посредника всем маршрутам в группе, вы можете использовать метод middleware перед определением группы. Посредники будут выполняться в том порядке, в котором они перечислены в массиве:

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // Использует посредники `first` и `second` ...
    });

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

Контроллеры

Если группа маршрутов использует один и тот же контроллер, вы можете использовать метод controller для определения общего контроллера всех маршрутов в группе. Затем при определении маршрутов вам нужно будет указать только метод вызываемого контроллера:

use App\Http\Controllers\OrderController;

Route::controller(OrderController::class)->group(function () {
    Route::get('/orders/{id}', 'show');
    Route::post('/orders', 'store');
});    

Маршрутизация поддоменов

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

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

Чтобы обеспечить доступность маршрутов поддоменов, вы должны зарегистрировать маршруты поддоменов перед регистрацией маршрутов корневого домена. Это предотвратит перезапись маршрутами корневого домена маршрутов поддоменов, имеющих одинаковый путь URI.

Префиксы URI сгруппированных маршрутов

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

Route::prefix('admin')->group(function () {
    Route::get('/users', function () {
        // Соответствует URL-адресу `/admin/users` ...
    });
});

Префиксы имен сгруппированных маршрутов

Метод name может быть использован для добавления префикса к каждому имени маршрута в группе с использованием заданной строки. Например, вы можете захотеть добавить префикс admin ко всем именам маршрутов в группе. Заданная строка добавляется к имени маршрута точно так, как она указана, поэтому мы обязательно предоставим знак . в конце префикса:

Route::name('admin.')->group(function () {
    Route::get('/users', function () {
        // Маршруту присвоено имя `admin.users` ...
    })->name('users');
});

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

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

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

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

use App\Models\User;

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

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

Конечно, неявная привязка также возможна при использовании методов контроллера. Опять же, обратите внимание, что сегмент {user} URI соответствует переменной $user в контроллере, которая типизирована как App\Models\User:

use App\Http\Controllers\UserController;
use App\Models\User;

// Определение маршрута ...
Route::get('/users/{user}', [UserController::class, 'show']);

// Определение метода контроллера ...
public function show(User $user)
{
    return view('user.profile', ['user' => $user]);
}

Программное удаление моделей

Как правило, неявная привязка модели не будет извлекать модели, которые были удалены программно. Однако вы можете указать неявной привязке извлекать эти модели, привязав метод withTrashed к определению вашего маршрута:

use App\Models\User;

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

Изменение ключа по умолчанию

По желанию можно извлекать модели Eloquent, используя столбец, отличный от id. Для этого вы можете указать столбец в определении параметра маршрута:

use App\Models\Post;

Route::get('/posts/{post:slug}', function (Post $post) {
    return $post;
});

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

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

Измененный ключ и ограничения неявной привязки модели

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

use App\Models\Post;
use App\Models\User;

Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
});

При использовании неявной привязки с измененным ключом в качестве параметра вложенного маршрута, Laravel автоматически задает ограничение запроса для получения вложенной модели своим родителем, используя соглашения, чтобы угадать имя отношения родительской модели. В этом случае предполагается, что модель User имеет отношение с именем posts (форма множественного числа имени параметра маршрута), которое можно использовать для получения модели Post.

При желании вы можете указать Laravel охватывать “дочерние” привязки, даже если пользовательский ключ не предоставлен. Для этого вы можете вызвать метод scopeBindings при определении своего маршрута:

use App\Models\Post;
use App\Models\User;

Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    return $post;
})->scopeBindings();

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

Route::scopeBindings()->group(function () {
    Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
        return $post;
    });
});

Точно так же, вы можете явно указать Laravel не использовать ограничение области действия привязок, вызвав метод withoutScopedBindings:

Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
})->withoutScopedBindings();

Настройка поведения при отсутствии модели

Обычно, если неявно связанная модель не найдена, то генерируется 404 HTTP-ответ. Однако вы можете изменить это поведение, вызвав метод missing при определении вашего маршрута. Метод missing принимает замыкание, которое будет вызываться, если неявно связанная модель не может быть найдена:

use App\Http\Controllers\LocationsController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;

Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])
        ->name('locations.view')
        ->missing(function (Request $request) {
            return Redirect::route('locations.index');
        });

Неявное привязывание Enum

PHP 8.1 ввёл поддержку Enum (Перечислений). Чтобы дополнить эту функцию, Laravel позволяет указывать поддерживаемый Enum в определении маршрута, и Laravel будет вызывать маршрут только в том случае, если сегмент маршрута соответствует допустимому значению Enum. В противном случае автоматически будет возвращен ответ HTTP 404. Например, учитывая следующий Enum:

<?php

namespace App\Enums;

enum Category: string
{
    case Fruits = 'fruits';
    case People = 'people';
}

Вы можете определить маршрут, который будет вызываться только в случае, если сегмент {category} маршрута является fruits или people. В противном случае Laravel вернет ответ HTTP 404:

use App\Enums\Category;
use Illuminate\Support\Facades\Route;

Route::get('/categories/{category}', function (Category $category) {
    return $category->value;
});

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

Вам необязательно использовать неявные привязки модели на основе соглашений Laravel, чтобы использовать привязку модели. Вы также можете явно определить, как параметры маршрута должны быть сопоставлены моделям. Чтобы зарегистрировать явную привязку, используйте метод маршрутизатора model, чтобы указать класс для переданного параметра. Вы должны определить ваши явные привязки модели в начале метода boot вашего класса AppServiceProvider:

use App\Models\User;
use Illuminate\Support\Facades\Route;

/**
 * Запуск любых служб приложения.
 */
public function boot(): void
{
    Route::model('user', User::class);
}

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

use App\Models\User;

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

Поскольку мы связали все параметры {user} с моделью App\Models\User, экземпляр этого класса будет внедрен в маршрут. Так, например, при запросе users/1 будет внедрен экземпляр User из базы данных с идентификатором 1.

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

Изменение логики связывания

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

use App\Models\User;
use Illuminate\Support\Facades\Route;

/**
 * Запуск любых служб приложения.
 */
public function boot(): void
{
    Route::bind('user', function (string $value) {
        return User::where('name', $value)->firstOrFail();
    });
}

В качестве альтернативы вы можете переопределить метод resolveRouteBinding вашей модели Eloquent. Этот метод получит значение сегмента URI и должен вернуть экземпляр класса, который должен быть внедрен в маршрут:

/**
 * Получить модель для привязанного к маршруту значения параметра.
 *
 * @param  mixed  $value
 * @param  string|null  $field
 * @return \Illuminate\Database\Eloquent\Model|null
 */
public function resolveRouteBinding($value, $field = null)
{
    return $this->where('name', $value)->firstOrFail();
}

Если в маршруте используется ограничения неявной привязки модели, то для получения связанной дочерней модели будет использоваться метод resolveChildRouteBinding родительской модели:

/**
 * Получить дочернюю модель для привязанного к маршруту значения параметра.
 *
 * @param  string  $childType
 * @param  mixed  $value
 * @param  string|null  $field
 * @return \Illuminate\Database\Eloquent\Model|null
 */
public function resolveChildRouteBinding($childType, $value, $field)
{
    return parent::resolveChildRouteBinding($childType, $value, $field);
}

Резервные маршруты

Используя метод Route::fallback, вы можете определить маршрут, который будет выполняться, когда ни один другой маршрут не соответствует входящему запросу. Как правило, необработанные запросы автоматически отображают страницу 404 через обработчик исключений вашего приложения. Однако, поскольку вы обычно определяете резервный маршрут в своем файле routes/web.php, то все посредники группы web будет применены к этому маршруту. При необходимости вы можете добавить дополнительный посредник для этого маршрута:

Route::fallback(function () {
    // ...
});

Резервный маршрут всегда должен быть последним зарегистрированным маршрутом в вашем приложении.

Ограничение частоты запросов

Определение ограничителей частоты запросов

Laravel включает в себя мощные и настраиваемые сервисы для ограничения частоты запросов, которые вы можете использовать для ограничения объема трафика для определенного маршрута или группы маршрутов. Чтобы начать, вам следует определить конфигурации ограничителей частоты запросов, соответствующие потребностям вашего приложения.

Ограничители скорости могут быть определены в методе boot класса App\Providers\AppServiceProvider вашего приложения:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;

/**
 * Запуск любых служб приложения.
 */
protected function boot(): void
{
    RateLimiter::for('api', function (Request $request) {
        return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
    });
}

Ограничители определяются с помощью метода for фасада RateLimiter. Метод for принимает имя ограничителя и замыкание, которое возвращает конфигурацию ограничений, применяемых к назначенным маршрутам. Конфигурация ограничений – это экземпляры класса Illuminate\Cache\RateLimiting\Limit. Этот класс содержит полезные методы «построения», чтобы вы могли быстро определить свой «лимит». Имя ограничителя может быть любой строкой по вашему желанию:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;

/**
 * Запуск любых служб приложения.
 */
protected function boot(): void
{
    RateLimiter::for('global', function (Request $request) {
        return Limit::perMinute(1000);
    });
}

Если входящий запрос превышает указанный лимит, то Laravel автоматически вернет ответ с 429 кодом состояния HTTP. Если вы хотите определить свой собственный ответ, который должен возвращаться, то вы можете использовать метод response:

RateLimiter::for('global', function (Request $request) {
    return Limit::perMinute(1000)->response(function (Request $request, array $headers) {
        return response('Custom response...', 429, $headers);
    });
});

Поскольку замыкание получает экземпляр входящего HTTP-запроса, то вы можете динамически создать ограничение на основе входящего запроса или статуса аутентификации пользователя:

RateLimiter::for('uploads', function (Request $request) {
    return $request->user()->vipCustomer()
                ? Limit::none()
                : Limit::perMinute(100);
});

Сегментация ограничений частоты запросов

Иногда может потребоваться сегментация ограничений по некоторым произвольным значениям. Например, вы можете разрешить пользователям получать доступ к указанному маршруту 100 раз в минуту на каждый IP-адрес. Для этого можно использовать метод by при построении лимита:

RateLimiter::for('uploads', function (Request $request) {
    return $request->user()->vipCustomer()
                ? Limit::none()
                : Limit::perMinute(100)->by($request->ip());
});

Чтобы проиллюстрировать эту функцию на другом примере, мы можем ограничить доступ к маршруту до 100 раз в минуту для каждого аутентифицированного ID пользователя или 10 раз в минуту для каждого IP-адреса для гостей:

RateLimiter::for('uploads', function (Request $request) {
    return $request->user()
                ? Limit::perMinute(100)->by($request->user()->id)
                : Limit::perMinute(10)->by($request->ip());
});

Множественные ограничения частоты запросов

При необходимости вы можете вернуть массив ограничений при указании конфигурации ограничителя. Каждое ограничение будет оцениваться для маршрута в зависимости от порядка, в котором они размещены в массиве:

RateLimiter::for('login', function (Request $request) {
    return [
        Limit::perMinute(500),
        Limit::perMinute(3)->by($request->input('email')),
    ];
});

Привязка ограничителей частоты запросов к маршрутам

Ограничители могут быть закреплены за маршрутами или группами маршрутов с помощью посредника throttle. Посредник throttle принимает имя ограничителя, которое вы хотите назначить маршруту:

Route::middleware(['throttle:uploads'])->group(function () {
    Route::post('/audio', function () {
        // ...
    });

    Route::post('/video', function () {
        // ...
    });
});

Использование Redis для посредника throttle

По умолчанию посредник throttle сопоставлен классу Illuminate\Routing\Middleware\ThrottleRequests. Однако, если вы используете Redis в качестве драйвера кэша вашего приложения, вы можете поручить Laravel использовать Redis для управления ограничением скорости. Для этого вам следует использовать метод throttleWithRedis в файле bootstrap/app.php вашего приложения. Этот метод сопоставляет посредника throttle с классом посредника Illuminate\Routing\Middleware\ThrottleRequestsWithRedis:

->withMiddleware(function (Middleware $middleware) {
    $middleware->throttleWithRedis();
    // ...
})

Подмена методов формы

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

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

Для удобства вы можете использовать директиву @method шаблонизатора Blade для создания поля ввода _method:

<form action="/example" method="POST">
    @method('PUT')
    @csrf
</form>

Доступ к текущему маршруту

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

use Illuminate\Support\Facades\Route;

$route = Route::current(); // Illuminate\Routing\Route
$name = Route::currentRouteName(); // string
$action = Route::currentRouteAction(); // string

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

Совместное использование ресурсов между источниками (CORS)

Laravel может автоматически отвечать на HTTP-запросы CORS OPTIONS значениями, которые вы сконфигурируете. Запросы OPTIONS будут автоматически обрабатываться HandleCors посредником, которое автоматически включается в глобальный стек промежуточного программного обеспечения вашего приложения.

Иногда вам может потребоваться настроить значения конфигурации CORS для вашего приложения. Вы можете сделать это, опубликовав файл конфигурации cors с помощью Artisan-команды config:publish:

php artisan config:publish cors

Эта команда поместит файл конфигурации cors.php в каталог config вашего приложения.

Для получения дополнительной информации о CORS и заголовках CORS обратитесь к веб-документации MDN по CORS.

Кеширование маршрутов

При развертывании вашего приложения на рабочем веб-сервере, вы должны воспользоваться кешем маршрутов Laravel. Использование кеша маршрутов резко сократит время, необходимое для регистрации всех маршрутов вашего приложения. Чтобы сгенерировать кеш маршрута, выполните команду route:cache Artisan:

php artisan route:cache

После выполнения этой команды ваш файл кеша маршрутов будет загружаться при каждом запросе. Помните, что если вы добавляете какие-либо новые маршруты, то вам нужно будет сгенерировать новый кеш маршрутов. По этой причине вы должны запускать команду route:cache только во время развертывания вашего проекта.

Вы можете использовать команду route:clear для очистки кеша маршрута:

php artisan route:clear