Роуты
Что такое роут
Роут — правило, которое сопоставляет URL + HTTP-метод с кодом, который должен выполниться.
Аналогия: роут = запись в таблице «если пришёл такой запрос, делай вот это».
Поток:
GET /posts/5 → Router ищет правило → находит → вызывает Controller@show(5)
Где регистрируются
routes/web.php— браузер, сессии, CSRF, cookie.routes/api.php— API, без сессий, префикс/api.routes/console.php— команды CLI.routes/channels.php— broadcast.
Простой роут
use Illuminate\Support\Facades\Route;
Route::get('/hello', function () {
return 'Hello, world!';
});
Разбор:
Route::get— метод фасадаRoute.'/hello'— URL.- Второй аргумент — замыкание или
[Controller::class, 'method'].
HTTP-методы
| Метод | Действие | Пример |
|---|---|---|
| GET | Читать | Список постов |
| POST | Создать | Новый пост |
| PUT | Обновить целиком | Пост полностью |
| PATCH | Обновить часть | Только заголовок |
| DELETE | Удалить | Удалить пост |
В Laravel:
Route::get('/posts', fn () => 'Список');
Route::post('/posts', fn () => 'Создание');
Route::put('/posts/{id}', fn ($id) => "Обновление {$id}");
Route::patch('/posts/{id}', fn ($id) => "Частичное {$id}");
Route::delete('/posts/{id}', fn ($id) => "Удаление {$id}");
Несколько методов
match:
Route::match(['get', 'post'], '/form', function () {
// оба метода
});
any:
Route::any('/webhook', function () {
// любой метод
});
Параметры роута
Обязательные:
Route::get('/user/{id}', function (string $id) {
return "ID: {$id}";
});
Несколько:
Route::get('/posts/{post}/comments/{comment}', function ($postId, $commentId) {
return "{$postId}, {$commentId}";
});
Порядок параметров в URL = порядок аргументов.
Необязательные:
Route::get('/user/{name?}', function (string $name = 'Guest') {
return "Hello, {$name}";
});
? — опционально. Обязательно значение по умолчанию.
Ограничения параметров
where:
Route::get('/user/{id}', function ($id) {
return $id;
})->where('id', '[0-9]+');
Если URL не подходит — 404.
Несколько:
Route::get('/user/{id}/{slug}', function ($id, $slug) {
//
})->where(['id' => '[0-9]+', 'slug' => '[a-z-]+']);
Хелперы:
->whereNumber('id') // только числа
->whereAlpha('slug') // только буквы
->whereAlphaNumeric('code') // буквы + цифры
->whereUuid('uuid') // UUID
->whereIn('type', ['a', 'b']) // из списка
Глобальные паттерны
В AppServiceProvider::boot():
use Illuminate\Support\Facades\Route;
public function boot(): void
{
Route::pattern('id', '[0-9]+');
}
Теперь любой {id} — только числа.
Именованные роуты
Имя роута — метка для генерации URL.
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
Использование:
$url = route('dashboard'); // /dashboard
// С параметром
Route::get('/posts/{post}', fn ($post) => $post)->name('posts.show');
route('posts.show', ['post' => 5]); // /posts/5
route('posts.show', 5); // то же
// С query
route('posts.show', ['post' => 5, 'tab' => 'comments']);
// /posts/5?tab=comments
Редирект по имени:
return redirect()->route('posts.index');
В Blade:
<a href="{{ route('posts.show', $post->id) }}">Читать</a>
Группы роутов
Группа применяет общие настройки к нескольким роутам.
Префикс
Route::prefix('admin')->group(function () {
Route::get('/users', fn () => 'Users'); // /admin/users
Route::get('/posts', fn () => 'Posts'); // /admin/posts
});
Middleware
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', fn () => 'Dashboard');
Route::get('/profile', fn () => 'Profile');
});
Имя
Route::name('admin.')->group(function () {
Route::get('/users', fn () => 'Users')->name('users'); // admin.users
Route::get('/posts', fn () => 'Posts')->name('posts'); // admin.posts
});
Комбинация
Route::middleware('auth')
->prefix('admin')
->name('admin.')
->group(function () {
Route::get('/users', fn () => 'Users')->name('users');
Route::get('/posts', fn () => 'Posts')->name('posts');
});
Домен
Route::domain('admin.example.com')->group(function () {
Route::get('/users', fn () => 'Users');
});
Динамический поддомен
Route::domain('{account}.example.com')->group(function () {
Route::get('/dashboard', function ($account) {
return "Account: {$account}";
});
});
Вложенные
Route::prefix('api')->group(function () {
Route::prefix('v1')->group(function () {
Route::get('/users', fn () => 'API v1 Users');
});
});
Просмотр роутов
php artisan route:list
php artisan route:list --path=admin
php artisan route:list --method=POST
php artisan route:list --name=posts
Продвинутые приёмы
Fallback
Если ничего не совпало:
Route::fallback(function () {
return response()->json(['error' => 'Not found'], 404);
});
Роуты для SPA
Route::get('/{any}', function () {
return view('app');
})->where('any', '.*');
Ловит все пути и отдаёт один шаблон.
⚠️ API-роуты должны быть раньше.
Пропуск CSRF для вебхука
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: [
'webhooks/*',
]);
})
Продвинутое — роутинг по файлам
Для больших проектов — разбить по файлам.
bootstrap/app.php:
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
then: function () {
Route::middleware('web')
->prefix('admin')
->name('admin.')
->group(base_path('routes/admin.php'));
},
)
Теперь routes/admin.php — отдельный файл.
Практика
Задача: сделать группу роутов для блога.
// routes/web.php
Route::prefix('blog')->name('blog.')->group(function () {
Route::get('/', [PostController::class, 'index'])->name('index');
Route::get('/{slug}', [PostController::class, 'show'])
->whereAlphaNumeric('slug')
->name('show');
Route::middleware('auth')->group(function () {
Route::get('/create', [PostController::class, 'create'])->name('create');
Route::post('/', [PostController::class, 'store'])->name('store');
});
});
// Использование
route('blog.index'); // /blog
route('blog.show', ['slug' => 'x']); // /blog/x
route('blog.create'); // /blog/create
Частые ошибки
1. Роут в api.php, но нужны сессии. Сессии только в web.php.
2. Параметры не в порядке:
Route::get('/posts/{post}/comments/{comment}', function ($comment, $post) { });
// Перепутаны местами
3. Забыли ->name():
route('posts.show'); // Route [posts.show] not defined
4. where не работает:
Route::get('/user/{id}', fn ($id) => $id)->where('id', '[0-9]+');
// Если параметр называется иначе — не сработает
5. fallback ловит всё, включая /api/*:
Route::fallback(fn () => '404');
// API тоже вернёт 404
Решение: проверять префикс в fallback.
Итог
- Роуты —
routes/web.phpиroutes/api.php. - HTTP-методы —
get,post,put,patch,delete. - Параметры —
{id},{id?}. - Ограничения —
where,whereNumber,whereUuid. - Имена —
->name(). - Группы —
prefix,middleware,name,domain. - Просмотр —
route:list. - Fallback — 404.
Дальше — контроллеры.