Роутинг — Laravel
- Базова маршрутизація
- Параметри маршруту
- Іменовані маршрути
- Групи маршрутів
- Привʼязка моделей до маршрутів
- Резервні маршрути
- Обмеження частоти запитів
- Підміна методу форми
- Доступ до поточного маршруту
- Cross-Origin Resource Sharing (CORS)
- Кешування маршрутів
Базова маршрутизація
Найпростіші маршрути Laravel приймають URI та замикання, надаючи дуже простий і виразний спосіб визначати маршрути й поведінку без складних конфігураційних файлів маршрутизації:
use Illuminate\Support\Facades\Route;
Route::get('/greeting', function () {
return 'Hello World';
});
Стандартні файли маршрутів
Усі маршрути Laravel визначаються у ваших файлах маршрутів, які розташовані в теці routes. Ці файли автоматично завантажуються Laravel за допомогою конфігурації, вказаної у файлі bootstrap/app.php вашого застосунку. Файл routes/web.php визначає маршрути для вашого вебінтерфейсу. Цим маршрутам призначено групу middleware 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-маршрути
Якщо ваш застосунок також пропонуватиме stateless API, ви можете увімкнути API-маршрутизацію за допомогою Artisan-команди install:api:
php artisan install:api
Команда install:api встановлює Laravel Sanctum, який надає надійний, але простий guard автентифікації за API-токеном, що може використовуватися для автентифікації сторонніх споживачів API, SPA або мобільних застосунків. Крім того, команда install:api створює файл routes/api.php:
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
Звісно, ви можете не використовувати middleware auth:sanctum на маршрутах, які мають бути публічно доступними.
Маршрути у routes/api.php є stateless і їм призначено групу middleware 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.
Маршрути представлень
Якщо вашому маршруту потрібно лише повернути представлення (view), ви можете скористатися методом 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
За замовчуванням middleware маршрутів, призначені кожному маршруту, не відображаються у виводі route:list; проте ви можете вказати Laravel відображати middleware маршруту та назви груп middleware, додавши до команди опцію -v:
php artisan route:list -v
# Розгорнути групи middleware...
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 у вашому маршруті. Наприклад, вам може знадобитися захопити ID користувача з 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());
Якщо вхідний запит не відповідає обмеженням шаблону маршруту, буде повернено HTTP-відповідь 404.
Глобальні обмеження
Якщо ви хочете, щоб параметр маршруту завжди обмежувався заданим регулярним виразом, ви можете скористатися методом pattern. Ці шаблони слід визначати в методі boot класу App\Providers\AppServiceProvider вашого застосунку:
use Illuminate\Support\Facades\Route;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::pattern('id', '[0-9]+');
}
Щойно шаблон визначено, він автоматично застосовується до всіх маршрутів, що використовують цю назву параметра:
Route::get('/user/{id}', function (string $id) {
// Виконується, лише якщо {id} числовий...
});
Закодовані прямі скісні риски
Компонент маршрутизації Laravel дозволяє всі символи, крім /, у значеннях параметрів маршруту. Ви маєте явно дозволити / бути частиною вашого плейсхолдера за допомогою регулярного виразу в умові where:
Route::get('/search/{search}', function (string $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 (string $id) {
// ...
})->name('profile');
$url = route('profile', ['id' => 1, 'photos' => 'yes']);
// http://example.com/user/1/profile?photos=yes
Примітка Інколи ви можете захотіти вказати значення за замовчуванням для параметрів URL на рівні всього запиту, як-от поточну локаль. Щоб зробити це, ви можете скористатися методом URL::defaults.
Перевірка поточного маршруту
Якщо ви хочете визначити, чи поточний запит було спрямовано до заданого іменованого маршруту, ви можете скористатися методом named на екземплярі Route. Наприклад, ви можете перевірити назву поточного маршруту з middleware маршруту:
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Handle an incoming request.
*
* @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);
}
Групи маршрутів
Групи маршрутів дозволяють вам спільно використовувати атрибути маршрутів, як-от middleware, у великій кількості маршрутів без потреби визначати ці атрибути в кожному окремому маршруті.
Вкладені групи намагаються розумно «зливати» атрибути з батьківською групою. Middleware й умови where зливаються, тоді як назви та префікси додаються в кінець. Роздільники просторів імен і скісні риски в префіксах URI додаються автоматично там, де це доречно.
Middleware
Щоб призначити middleware усім маршрутам у групі, ви можете скористатися методом middleware перед визначенням групи. Middleware виконуються в тому порядку, у якому вони перелічені в масиві:
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Використовує middleware first і second...
});
Route::get('/user/profile', function () {
// Використовує middleware 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) {
// ...
});
});
Префікси маршрутів
Метод 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');
});
Привʼязка моделей до маршрутів
Коли ви впроваджуєте ID моделі в маршрут або дію контролера, вам часто доводиться робити запит до бази даних, щоб отримати модель, яка відповідає цьому ID. Привʼязка моделей до маршрутів у Laravel надає зручний спосіб автоматично впроваджувати екземпляри моделей безпосередньо у ваші маршрути. Наприклад, замість того щоб впроваджувати ID користувача, ви можете впровадити цілий екземпляр моделі User, що відповідає заданому ID.
Неявна привʼязка
Laravel автоматично розвʼязує моделі Eloquent, визначені в маршрутах або діях контролерів, чиї імена змінних із зазначеним типом збігаються з назвою сегмента маршруту. Наприклад:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
return $user->email;
});
Оскільки для змінної $user вказано тип моделі Eloquent App\Models\User, а назва змінної збігається із сегментом URI {user}, Laravel автоматично впровадить екземпляр моделі, ID якого відповідає значенню з URI запиту. Якщо відповідного екземпляра моделі в базі даних не знайдено, буде автоматично згенеровано HTTP-відповідь 404.
Звісно, неявна привʼязка також можлива при використанні методів контролера. Знову ж таки, зауважте, що сегмент URI {user} збігається зі змінною $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, при отриманні заданого класу моделі, ви можете застосувати до моделі Eloquent атрибут RouteKey:
use Illuminate\Database\Eloquent\Attributes\RouteKey;
use Illuminate\Database\Eloquent\Model;
#[RouteKey('slug')]
class Post extends Model
{
// ...
}
Власні ключі та обмеження області
Коли ви неявно привʼязуєте кілька моделей Eloquent в одному визначенні маршруту, ви можете захотіти обмежити область другої моделі Eloquent так, щоб вона обовʼязково була дочірньою до попередньої моделі Eloquent. Наприклад, розгляньмо це визначення маршруту, яке отримує допис блогу за слагом для конкретного користувача:
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();
Налаштування поведінки за відсутності моделі
Зазвичай, якщо неявно привʼязану модель не знайдено, буде згенеровано HTTP-відповідь 404. Проте ви можете налаштувати цю поведінку, викликавши метод 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');
});
Неявна привʼязка переліків
PHP 8.1 запровадив підтримку переліків (Enums). На доповнення до цієї можливості Laravel дозволяє вам вказати у визначенні маршруту тип переліку, підкріпленого рядком (string-backed Enum), і Laravel викличе маршрут, лише якщо цей сегмент маршруту відповідає дійсному значенню переліку. Інакше буде автоматично повернено HTTP-відповідь 404. Наприклад, за наявності такого переліку:
<?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;
/**
* Bootstrap any application services.
*/
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 із бази даних, який має ID 1.
Якщо відповідного екземпляра моделі в базі даних не знайдено, буде автоматично згенеровано HTTP-відповідь 404.
Налаштування логіки розвʼязання
Якщо ви хочете визначити власну логіку розвʼязання привʼязки моделей, ви можете скористатися методом Route::bind. Замикання, яке ви передаєте методу bind, отримає значення сегмента URI та має повернути екземпляр класу, який слід впровадити в маршрут. Знову ж таки, це налаштування має відбуватися в методі boot класу AppServiceProvider вашого застосунку:
use App\Models\User;
use Illuminate\Support\Facades\Route;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::bind('user', function (string $value) {
return User::where('name', $value)->firstOrFail();
});
}
Як альтернативу ви можете перевизначити метод resolveRouteBinding у вашій моделі Eloquent. Цей метод отримає значення сегмента URI та має повернути екземпляр класу, який слід впровадити в маршрут:
/**
* Retrieve the model for a bound value.
*
* @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:
/**
* Retrieve the child model for a bound value.
*
* @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» через обробник винятків вашого застосунку. Проте, оскільки ви зазвичай визначаєте маршрут fallback у файлі routes/web.php, до цього маршруту буде застосовано всі middleware з групи middleware web. Ви можете вільно додавати додаткові middleware до цього маршруту за потреби:
Route::fallback(function () {
// ...
});
Обмеження частоти запитів
Визначення обмежувачів частоти
Laravel містить потужні й налаштовувані сервіси обмеження частоти запитів, які ви можете використовувати для обмеження обсягу трафіку для заданого маршруту або групи маршрутів. Щоб почати, вам слід визначити конфігурації обмежувачів частоти, що відповідають потребам вашого застосунку.
Обмежувачі частоти можна визначити в методі boot класу App\Providers\AppServiceProvider вашого застосунку:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
/**
* Bootstrap any application services.
*/
public 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;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000);
});
}
Якщо вхідний запит перевищує вказане обмеження частоти, Laravel автоматично поверне відповідь із кодом HTTP-статусу 429. Якщо ви хочете визначити власну відповідь, яку має повертати обмеження частоти, ви можете скористатися методом 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::perHour(10);
});
Сегментування обмежень частоти
Інколи ви можете захотіти сегментувати обмеження частоти за якимось довільним значенням. Наприклад, ви можете захотіти дозволити користувачам звертатися до заданого маршруту 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')),
];
});
Якщо ви призначаєте кілька обмежень частоти, сегментованих за однаковими значеннями by, вам слід переконатися, що кожне значення by є унікальним. Найпростіший спосіб досягти цього — додати префікс до значень, переданих методу by:
RateLimiter::for('uploads', function (Request $request) {
return [
Limit::perMinute(10)->by('minute:'.$request->user()->id),
Limit::perDay(1000)->by('day:'.$request->user()->id),
];
});
Обмеження частоти на основі відповіді
Окрім обмеження частоти вхідних запитів, Laravel дозволяє вам обмежувати частоту на основі відповіді за допомогою методу after. Це корисно, коли ви хочете зараховувати до обмеження частоти лише певні відповіді, як-от помилки валідації, відповіді 404 або інші конкретні коди HTTP-статусів.
Метод after приймає замикання, яке отримує відповідь і має повертати true, якщо відповідь слід зарахувати до обмеження частоти, або false, якщо її слід ігнорувати. Це особливо корисно для запобігання атакам перебором (enumeration attacks) шляхом обмеження послідовних відповідей 404 або для того, щоб дозволити користувачам повторювати запити, які не пройшли валідацію, не вичерпуючи своє обмеження частоти на ендпоінті, який має обмежувати лише успішні операції:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Symfony\Component\HttpFoundation\Response;
RateLimiter::for('resource-not-found', function (Request $request) {
return Limit::perMinute(10)
->by($request->user()?->id ?: $request->ip())
->after(function (Response $response) {
// Зараховувати до обмеження частоти лише відповіді 404, щоб запобігти перебору...
return $response->status() === 404;
});
});
Приєднання обмежувачів частоти до маршрутів
Обмежувачі частоти можна приєднувати до маршрутів або груп маршрутів за допомогою middleware throttle. Middleware throttle приймає назву обмежувача частоти, який ви хочете призначити маршруту:
Route::middleware(['throttle:uploads'])->group(function () {
Route::post('/audio', function () {
// ...
});
Route::post('/video', function () {
// ...
});
});
Обмеження частоти за допомогою Redis
За замовчуванням middleware throttle зіставлено з класом Illuminate\Routing\Middleware\ThrottleRequests. Проте, якщо ви використовуєте Redis як драйвер кешу вашого застосунку, ви можете захотіти вказати Laravel використовувати Redis для керування обмеженням частоти. Щоб зробити це, вам слід скористатися методом throttleWithRedis у файлі bootstrap/app.php вашого застосунку. Цей метод зіставляє middleware throttle із класом middleware Illuminate\Routing\Middleware\ThrottleRequestsWithRedis:
->withMiddleware(function (Middleware $middleware): void {
$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>
Для зручності ви можете скористатися Blade-директивою @method, щоб згенерувати поле введення _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, щоб переглянути всі методи, доступні в класах роутера та маршруту.
Cross-Origin Resource Sharing (CORS)
Laravel може автоматично відповідати на CORS HTTP-запити OPTIONS значеннями, які ви налаштуєте. Запити OPTIONS автоматично оброблятиме middleware HandleCors, який автоматично включено до глобального стека middleware вашого застосунку.
Інколи вам може знадобитися налаштувати значення конфігурації CORS для вашого застосунку. Ви можете зробити це, опублікувавши конфігураційний файл cors за допомогою Artisan-команди config:publish:
php artisan config:publish cors
Ця команда розмістить конфігураційний файл cors.php у теці config вашого застосунку.
Примітка Для отримання додаткової інформації про CORS і заголовки CORS, будь ласка, зверніться до вебдокументації MDN щодо CORS.
Кешування маршрутів
Розгортаючи ваш застосунок у продакшн, вам слід скористатися перевагами кешу маршрутів Laravel. Використання кешу маршрутів різко зменшить час, потрібний для реєстрації всіх маршрутів вашого застосунку. Щоб згенерувати кеш маршрутів, виконайте Artisan-команду route:cache:
php artisan route:cache
Після виконання цієї команди ваш файл кешованих маршрутів завантажуватиметься при кожному запиті. Памʼятайте: якщо ви додасте якісь нові маршрути, вам потрібно буде згенерувати свіжий кеш маршрутів. Через це вам слід виконувати команду route:cache лише під час розгортання вашого проєкту.
Ви можете скористатися командою route:clear, щоб очистити кеш маршрутів:
php artisan route:clear
Виправити терміни, дописати розділ або взяти нову главу може кожен. Термінологію узгоджуємо в глосарії, щоб переклад лишався однорідним.