Глава 5.2: Создание простых представлений для API
Время изучения: 45 минут
1. Задача: Визуализировать данные
Наш API в Главе 2 умеет отдавать данные в формате JSON. Это отлично для машин, но люди предпочитают видеть информацию на красиво оформленных веб-страницах. Наша цель — создать две такие страницы:
- Список всех планет (
/planets
) - Страница одной планеты (
/planets/{id}
)
Для этого мы будем использовать связку "Маршрут → Контроллер → Вид".
💡 Космическая аналогия:
Представьте, что JSON от API — это сырые данные телеметрии, просто поток цифр. Наша задача сегодня — создать в ЦУП два экрана (два "вида"):
- Общий экран: показывает статус всех объектов в системе (список планет).
- Детальный экран: при клике на объект выводит всю информацию о нём (страница одной планеты).
2. Шаг 1: Создание контроллера для веб-страниц
Для чистоты архитектуры не стоит смешивать логику API и логику веб-страниц в одном контроллере. Создадим новый контроллер специально для отображения наших Blade-видов.
Выполните в терминале:
Мы создаем его в подпапкеWeb
, чтобы отделить от API-контроллеров.
Откройте созданный файл app/Http/Controllers/Web/PlanetPageController.php
.
Шаг 2: Страница со списком всех планет
1. Создаем метод в контроллере:
В PlanetPageController
добавьте метод index
, который будет получать все планеты из базы данных и передавать их в вид.
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use App\Models\Planet; // Не забудьте импортировать модель
class PlanetPageController extends Controller
{
/**
* Показывает страницу со списком всех планет.
*/
public function index()
{
// 1. Получаем все планеты из БД
$planets = Planet::all();
// 2. Возвращаем вид и передаем в него данные
return view('planets.index', ['planets' => $planets]);
}
}
2. Создаем Blade-вид:
Создайте файл resources/views/planets/index.blade.php
. Мы будем использовать макет, созданный в прошлой главе.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Planets</title>
<style>
body {
font-family: sans-serif;
background-color: #f4f4f9;
color: #333;
margin: 0;
padding: 2em;
}
.container {
max-width: 960px;
margin: 0 auto;
}
h2 {
color: #1a202c;
}
hr {
border: none;
border-top: 1px solid #e2e8f0;
margin: 1.5em 0;
}
.planet-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5em;
}
.planet-card {
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.5em;
padding: 1.5em;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
transition: transform 0.2s;
}
.planet-card:hover {
transform: translateY(-5px);
}
.planet-card h3 {
margin-top: 0;
color: #2d3748;
}
.planet-card p {
margin-bottom: 0.5em;
color: #4a5568;
}
.planet-card a {
color: #4299e1;
text-decoration: none;
font-weight: bold;
}
.planet-card a:hover {
text-decoration: underline;
}
.no-planets {
color: #718096;
}
</style>
</head>
<body>
<div class="container">
<h2>Список всех известных планет</h2>
<hr>
<div class="planet-list">
@forelse($planets as $planet)
<div class="planet-card">
<h3>{{ $planet->name }}</h3>
<p>Солнечная система: {{ $planet->solar_system }}</p>
<p>Диаметр: {{ number_format($planet->size_km, 0, '.', ' ') }} км</p>
<a href="/planets/{{ $planet->id }}">Узнать больше →</a>
</div>
@empty
<p class="no-planets">В базе данных нет ни одной планеты. Пожалуйста, запустите сидеры.</p>
@endforelse
</div>
</div>
</body>
</html>
number_format(...)
— это обычная PHP-функция для красивого форматирования чисел. Её можно использовать прямо в Blade.
3. Создаем маршрут в routes/web.php
:
use App\Http\Controllers\Web\PlanetPageController;
// ...
Route::get('/planets', [PlanetPageController::class, 'index']);
/planets
в браузере, вы увидите страницу со списком планет!
4. Шаг 3: Страница одной планеты
1. Создаем метод в контроллере:
В PlanetPageController
добавим метод show
. Благодаря Route Model Binding, Laravel автоматически найдет планету по ID и передаст ее в метод.
<?php
// Внутри класса PlanetPageController
/**
* Показывает страницу одной конкретной планеты.
*/
public function show(Planet $planet)
{
// Laravel уже нашел для нас планету.
// Если она не найдена, он автоматически вернет 404 ошибку.
return view('planets.show', ['planet' => $planet]);
}
2. Создаем Blade-вид:
Создайте файл resources/views/planets/show.blade.php
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ $planet->name }}</title>
<style>
body {
font-family: sans-serif;
background-color: #f4f4f9;
color: #333;
margin: 0;
padding: 2em;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
max-width: 600px;
width: 100%;
}
.planet-detail {
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.5em;
padding: 2em;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.planet-detail h1 {
margin-top: 0;
color: #2d3748;
}
.planet-detail p {
margin-bottom: 1em;
color: #4a5568;
font-size: 1.1em;
}
.back-link {
display: inline-block;
margin-top: 1.5em;
color: #4299e1;
text-decoration: none;
font-weight: bold;
}
.back-link:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<div class="planet-detail">
@if($planet->image_url)
<img src="{{ $planet->image_url }}" alt="Image of {{ $planet->name }}" style="max-width: 100%; height: auto; border-radius: 0.5em; margin-bottom: 1em;">
@endif
<h1>{{ $planet->name }}</h1>
@if($planet->description)
<p>{{ $planet->description }}</p>
@endif
<p><strong>Солнечная система:</strong> {{ $planet->solar_system }}</p>
<p><strong>Диаметр:</strong> {{ number_format($planet->size_km, 0, '.', ' ') }} км</p>
<a href="/planets" class="back-link">← Назад к списку планет</a>
</div>
</div>
</body>
</html>
3. Создаем маршрут в routes/web.php
:
// Добавьте этот маршрут после маршрута для /planets
Route::get('/planets/{planet}', [PlanetPageController::class, 'show']);
{planet}
должно совпадать с именем переменной в методе контроллера (show(Planet $planet)
) для корректной работы Route Model Binding.
Теперь, кликнув на ссылку "Узнать больше" на странице со списком, вы попадете на детальную страницу конкретной планеты.
Квиз для закрепления
🚀 Итог главы:
Вы успешно создали "витрину" для своего API, используя архитектуру Laravel MVC. Теперь у вас есть:
- Отдельный контроллер для логики веб-страниц.
- Динамическая страница со списком всех планет, получающая данные из БД.
- Детальная страница для каждой планеты с использованием Route Model Binding.
- Два веб-маршрута в
routes/web.php
для доступа к этим страницам.
Вы превратили сырые данные в понятную и полезную информацию для пользователя. В следующей главе мы добавим интерактивности, встроив JavaScript в наши Blade-виды для взаимодействия с API без перезагрузки страницы.