Skip to content

Глава 5.5: Роутинг для веб-страниц

Время изучения: 40 минут


1. routes/web.php vs routes/api.php: Два разных пульта управления

Важно еще раз закрепить фундаментальное различие:

Характеристика routes/web.php (Веб-пульт) routes/api.php (API-пульт)
Основная задача Отображение HTML-страниц, обработка форм Предоставление данных в формате JSON для других приложений
Состояние (State) Stateful (с состоянием) — использует сессии и cookies Stateless (без состояния) — каждый запрос независим
Middleware по умолчанию web (включает сессии, CSRF-защиту, шифрование cookies) api (включает "throttling" — ограничение частоты запросов)
Префикс URL Нет (корень вашего сайта) /api/ (настраивается в RouteServiceProvider)
Аутентификация Обычно через сессии (Login/Password) Обычно через токены (Sanctum, Passport)

Мы работаем с routes/web.php, чтобы построить интерфейс для живого человека.


2. Ресурсные маршруты для веба

Подобно Route::apiResource, для веба существует Route::resource. Он создает маршруты для полного CRUD-цикла, включая страницы для отображения форм создания и редактирования.

Давайте создадим полный набор маршрутов для управления нашими планетами через веб-интерфейс.

Шаг 1: Создаем маршрут в routes/web.php

Закомментируйте или удалите старые маршруты для /planets и замените их одной строкой:

use App\Http\Controllers\Web\PlanetPageController;

// Route::get('/planets', [PlanetPageController::class, 'index']);
// Route::get('/planets/{planet}', [PlanetPageController::class, 'show']);

Route::resource('planets', PlanetPageController::class);

Шаг 2: Смотрим, что было создано Выполните в терминале команду php artisan route:list --except-vendor:

+--------+-----------+------------------------+------------------+-------------------------------------------------+------------+
| Method | URI       | Name                   | Action           | Middleware                                      |
+--------+-----------+------------------------+------------------+-------------------------------------------------+------------+
| GET|HEAD | planets                | planets.index          | ...\PlanetPageController@index                    | web        |
| POST   | planets                | planets.store          | ...\PlanetPageController@store                    | web        |
| GET|HEAD | planets/create         | planets.create         | ...\PlanetPageController@create                   | web        |
| GET|HEAD | planets/{planet}       | planets.show           | ...\PlanetPageController@show                     | web        |
| PUT|PATCH | planets/{planet}       | planets.update         | ...\PlanetPageController@update                   | web        |
| DELETE | planets/{planet}       | planets.destroy        | ...\PlanetPageController@destroy                  | web        |
| GET|HEAD | planets/{planet}/edit  | planets.edit           | ...\PlanetPageController@edit                     | web        |
+--------+-----------+------------------------+------------------+-------------------------------------------------+------------+

Route::resource создал для нас 7 маршрутов, включая:

  • planets.create (GET /planets/create): страница с формой создания.
  • planets.store (POST /planets): обработка этой формы.
  • planets.edit (GET /planets/{planet}/edit): страница с формой редактирования.
  • planets.update (PUT/PATCH /planets/{planet}): обработка формы редактирования.
  • planets.destroy (DELETE /planets/{planet}): удаление ресурса.

3. Именованные маршруты: Удобные "космические координаты"

Обратите внимание на колонку Name. Laravel автоматически присвоил каждому маршруту уникальное имя (например, planets.index). Использовать имена вместо жестко прописанных URL — это лучшая практика.

Почему? Если вы решите изменить URL с /planets на /worlds, вам не придется искать и менять все ссылки в ваших шаблонах. Вы просто меняете его в одном месте — в файле роутов, а имена остаются прежними.

Пример использования в Blade:

Раньше мы писали так:

<a href="/planets/{{ $planet->id }}">Узнать больше &rarr;</a>

Теперь мы будем писать так, используя хелпер route():

<a href="{{ route('planets.show', ['planet' => $planet->id]) }}">Узнать больше &rarr;</a>

  • route('planets.show', ...) — генерирует URL для маршрута с именем planets.show.
  • ['planet' => $planet->id] — передает необходимые параметры в URL. Laravel сам подставит ID в {planet}. Можно даже передать всю модель: ['planet' => $planet].

4. Реализация недостающих методов в контроллере

Route::resource создал маршруты, но соответствующие методы в PlanetPageController нам нужно создать самим.

Откройте app/Http/Controllers/Web/PlanetPageController.php и добавим их.

<?php
use Illuminate\Http\Request; // <-- Добавить

class PlanetPageController extends Controller
{
    // index() и show() у нас уже есть

    /**
     * Показывает форму для создания новой планеты.
     */
    public function create()
    {
        return view('planets.create'); // Просто возвращаем вид с формой
    }

    /**
     * Сохраняет новую планету в базе данных.
     */
    public function store(Request $request)
    {
        // Валидация данных из формы
        $validated = $request->validate([
            'name' => 'required|string|max:255|unique:planets',
            'solar_system' => 'required|string|max:100',
            // ... другие правила
        ]);

        Planet::create($validated);

        // Перенаправляем пользователя на страницу со списком с сообщением об успехе
        return redirect()->route('planets.index')->with('success', 'Планета успешно создана!');
    }

    /**
     * Показывает форму для редактирования планеты.
     */
    public function edit(Planet $planet)
    {
        return view('planets.edit', ['planet' => $planet]);
    }

    /**
     * Обновляет данные планеты в базе данных.
     */
    public function update(Request $request, Planet $planet)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255|unique:planets,name,' . $planet->id,
            'solar_system' => 'required|string|max:100',
        ]);

        $planet->update($validated);

        return redirect()->route('planets.show', $planet)->with('success', 'Данные о планете обновлены!');
    }

    /**
     * Удаляет планету.
     */
    public function destroy(Planet $planet)
    {
        $planet->delete();

        return redirect()->route('planets.index')->with('success', 'Планета списана.');
    }
}
  • redirect()->route(...) — перенаправляет пользователя на другой именованный маршрут.
  • ->with('success', '...') — добавляет "флеш-сообщение" в сессию, которое будет доступно на следующей странице ровно один раз. Мы можем отобразить его в нашем Blade-шаблоне.

5. Группировка маршрутов

Если у вас много маршрутов с общими характеристиками (например, все они для админ-панели и должны иметь префикс /admin и специальный middleware), их можно сгруппировать.

<?php
Route::middleware(['auth', 'admin'])->prefix('admin')->name('admin.')->group(function () {
    // Все маршруты внутри этой группы будут иметь:
    // 1. Middleware 'auth' и 'admin'
    // 2. Префикс URL '/admin' (например, /admin/planets)
    // 3. Префикс имени 'admin.' (например, admin.planets.index)

    Route::resource('planets', PlanetPageController::class);
    // Route::get('/dashboard', ...)->name('dashboard'); // -> admin.dashboard
});

Квиз для закрепления

1. Какая команда в `routes/web.php` создаст полный набор CRUD-маршрутов для веб-интерфейса?

2. В чем главное преимущество использования именованных маршрутов?

3. Какой маршрут будет сгенерирован для метода `create()` в `Route::resource('articles', ...)`?

4. Что делает код `redirect()->route('home')->with('status', 'OK')`?

5. Для чего используется `Route::prefix('dashboard')`?


🚀 Итог главы:

Вы освоили структурированный и профессиональный подход к организации веб-маршрутов в Laravel. Теперь вы умеете:

  • Различать web и api маршруты и их предназначение.
  • Использовать Route::resource для быстрой генерации стандартных CRUD-маршрутов.
  • Применять именованные маршруты для создания гибкого и поддерживаемого кода.
  • Создавать полные CRUD-операции в контроллере с валидацией и редиректами.
  • Группировать маршруты для применения общих правил.

Навигационная система вашего "корабля" теперь отказоустойчива и готова к расширению. В финальной главе этого раздела мы соединим все полученные знания и отобразим данные о планетах, полученные через Fetch, на нашей Blade-странице.