Capítulo 5.2: Criando Visões Simples para API
Tempo de estudo: 45 minutos
1. Tarefa: Visualizar dados
Nossa API no Capítulo 2 é capaz de fornecer dados no formato JSON. Isso é excelente para máquinas, mas as pessoas preferem ver as informações em páginas web bem projetadas. Nosso objetivo é criar duas dessas páginas:
- Lista de todos os planetas (
/planets
) - Página de um único planeta (
/planets/{id}
)
Para isso, usaremos a combinação "Rota → Controlador → Visão".
💡 Analogia espacial:
Imagine que o JSON da API são dados brutos de telemetria, apenas um fluxo de números. Nossa tarefa hoje é criar dois monitores (duas "visões") no Centro de Controle de Missão:
- Tela geral: mostra o status de todos os objetos no sistema (lista de planetas).
- Tela detalhada: ao clicar em um objeto, exibe todas as informações sobre ele (página de um planeta).
2. Passo 1: Criando um controlador para páginas web
Para a pureza da arquitetura, não se deve misturar a lógica da API e a lógica das páginas web em um único controlador. Criaremos um novo controlador especificamente para exibir nossas views Blade.
Execute no terminal:
Estamos criando-o na subpastaWeb
para separá-lo dos controladores de API.
Abra o arquivo criado app/Http/Controllers/Web/PlanetPageController.php
.
Passo 2: Página com a lista de todos os planetas
1. Criando um método no controlador:
Em PlanetPageController
, adicione o método index
, que obterá todos os planetas do banco de dados e os passará para a view.
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use App\Models\Planet; // Não se esqueça de importar o modelo
class PlanetPageController extends Controller
{
/**
* Mostra a página com a lista de todos os planetas.
*/
public function index()
{
// 1. Obtém todos os planetas do BD
$planets = Planet::all();
// 2. Retorna a view e passa os dados para ela
return view('planets.index', ['planets' => $planets]);
}
}
2. Criando uma view Blade:
Crie o arquivo resources/views/planets/index.blade.php
. Usaremos o layout criado no capítulo anterior.
<!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>Lista de todos os planetas conhecidos</h2>
<hr>
<div class="planet-list">
@forelse($planets as $planet)
<div class="planet-card">
<h3>{{ $planet->name }}</h3>
<p>Sistema Solar: {{ $planet->solar_system }}</p>
<p>Diâmetro: {{ number_format($planet->size_km, 0, '.', ' ') }} km</p>
<a href="/planets/{{ $planet->id }}">Saber mais →</a>
</div>
@empty
<p class="no-planets">Não há nenhum planeta no banco de dados. Por favor, execute os seeders.</p>
@endforelse
</div>
</div>
</body>
</html>
number_format(...)
— é uma função PHP comum para formatar números de forma elegante. Pode ser usada diretamente no Blade.
3. Criando uma rota em routes/web.php
:
use App\Http\Controllers\Web\PlanetPageController;
// ...
Route::get('/planets', [PlanetPageController::class, 'index']);
/planets
no navegador, você verá a página com a lista de planetas!
4. Passo 3: Página de um único planeta
1. Criando um método no controlador:
Em PlanetPageController
, adicionaremos o método show
. Graças ao Route Model Binding, Laravel encontrará automaticamente o planeta pelo ID e o passará para o método.
<?php
// Dentro da classe PlanetPageController
/**
* Mostra a página de um planeta específico.
*/
public function show(Planet $planet)
{
// O Laravel já encontrou o planeta para nós.
// Se não for encontrado, ele retornará automaticamente um erro 404.
return view('planets.show', ['planet' => $planet]);
}
2. Criando uma view Blade:
Crie o arquivo 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>Sistema Solar:</strong> {{ $planet->solar_system }}</p>
<p><strong>Diâmetro:</strong> {{ number_format($planet->size_km, 0, '.', ' ') }} km</p>
<a href="/planets" class="back-link">← Voltar para a lista de planetas</a>
</div>
</div>
</body>
</html>
3. Criando uma rota em routes/web.php
:
// Adicione esta rota após a rota para /planets
Route::get('/planets/{planet}', [PlanetPageController::class, 'show']);
{planet}
deve corresponder ao nome da variável no método do controlador (show(Planet $planet)
) para que o Route Model Binding funcione corretamente.
Agora, ao clicar no link "Saber mais" na página da lista, você será direcionado para a página detalhada de um planeta específico.
Quiz para consolidação
🚀 Resumo do Capítulo:
Você criou com sucesso uma "vitrine" para sua API, usando a arquitetura Laravel MVC. Agora você tem:
- Um controlador separado para a lógica das páginas web.
- Uma página dinâmica com uma lista de todos os planetas, obtendo dados do BD.
- Uma página de detalhes para cada planeta usando Route Model Binding.
- Duas rotas web em
routes/web.php
para acessar essas páginas.
Você transformou dados brutos em informações compreensíveis e úteis para o usuário. No próximo capítulo, adicionaremos interatividade, incorporando JavaScript em nossas views Blade para interagir com a API sem recarregar a página.