Skip to content

Chapitre 5.2 : Création de vues simples pour l'API

Temps d'étude : 45 minutes


1. Objectif : Visualiser les données

Notre API au Chapitre 2 est capable de renvoyer des données au format JSON. C'est excellent pour les machines, mais les humains préfèrent voir les informations sur des pages web joliment conçues. Notre objectif est de créer deux pages de ce type :

  1. Liste de toutes les planètes (/planets)
  2. Page d'une seule planète (/planets/{id})

Pour cela, nous utiliserons la combinaison "Route → Contrôleur → Vue".

💡 Analogie spatiale :

Imaginez que le JSON de l'API sont des données de télémétrie brutes, juste un flux de chiffres. Notre tâche aujourd'hui est de créer deux écrans (deux "vues") au centre de contrôle :

  • Écran général : affiche le statut de tous les objets du système (liste des planètes).
  • Écran détaillé : en cliquant sur un objet, affiche toutes les informations le concernant (page d'une seule planète).

2. Étape 1 : Création du contrôleur pour les pages web

Pour la pureté de l'architecture, il ne faut pas mélanger la logique de l'API et la logique des pages web dans un seul contrôleur. Nous allons créer un nouveau contrôleur spécifiquement pour afficher nos vues Blade.

Exécutez dans le terminal :

php artisan make:controller Web/PlanetPageController
Nous le créons dans le sous-dossier Web pour le séparer des contrôleurs d'API.

Ouvrez le fichier créé app/Http/Controllers/Web/PlanetPageController.php.


Étape 2 : Page avec la liste de toutes les planètes

1. Création d'une méthode dans le contrôleur : Dans PlanetPageController, ajoutez la méthode index qui récupérera toutes les planètes de la base de données et les transmettra à la vue.

<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Planet; // N'oubliez pas d'importer le modèle

class PlanetPageController extends Controller
{
    /**
     * Affiche la page avec la liste de toutes les planètes.
     */
    public function index()
    {
        // 1. Récupérons toutes les planètes de la BDD
        $planets = Planet::all();

        // 2. Retournons la vue et transmettons les données
        return view('planets.index', ['planets' => $planets]);
    }
}

2. Création de la vue Blade : Créez le fichier resources/views/planets/index.blade.php. Nous utiliserons la mise en page créée dans le chapitre précédent.

<!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>Liste de toutes les planètes connues</h2>
        <hr>
        <div class="planet-list">
            @forelse($planets as $planet)
                <div class="planet-card">
                    <h3>{{ $planet->name }}</h3>
                    <p>Système solaire : {{ $planet->solar_system }}</p>
                    <p>Diamètre : {{ number_format($planet->size_km, 0, '.', ' ') }} km</p>
                    <a href="/planets/{{ $planet->id }}">En savoir plus &rarr;</a>
                </div>
            @empty
                <p class="no-planets">Il n'y a aucune planète dans la base de données. Veuillez exécuter les seeders.</p>
            @endforelse
        </div>
    </div>
</body>
</html>
  • number_format(...) est une fonction PHP standard pour un formatage agréable des nombres. Elle peut être utilisée directement dans Blade.

3. Création de la route dans routes/web.php :

use App\Http\Controllers\Web\PlanetPageController;

// ...

Route::get('/planets', [PlanetPageController::class, 'index']);
Maintenant, si vous vous rendez à l'adresse /planets dans votre navigateur, vous verrez la page avec la liste des planètes !


4. Étape 3 : Page d'une seule planète

1. Création d'une méthode dans le contrôleur :

Dans PlanetPageController, nous ajouterons la méthode show. Grâce au Route Model Binding, Laravel trouvera automatiquement la planète par son ID et la transmettra à la méthode.

<?php
// À l'intérieur de la classe PlanetPageController
/**
 * Affiche la page d'une planète spécifique.
 */
public function show(Planet $planet)
{
    // Laravel a déjà trouvé la planète pour nous.
    // Si elle n'est pas trouvée, il retournera automatiquement une erreur 404.

    return view('planets.show', ['planet' => $planet]);
}

2. Création de la vue Blade :

Créez le fichier 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 de {{ $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>Système solaire :</strong> {{ $planet->solar_system }}</p>
            <p><strong>Diamètre :</strong> {{ number_format($planet->size_km, 0, '.', ' ') }} km</p>
            <a href="/planets" class="back-link">&larr; Retour à la liste des planètes</a>
        </div>
    </div>
</body>
</html>

3. Création de la route dans routes/web.php :

// Ajoutez cette route après la route pour /planets
Route::get('/planets/{planet}', [PlanetPageController::class, 'show']);
- Le nom du paramètre {planet} doit correspondre au nom de la variable dans la méthode du contrôleur (show(Planet $planet)) pour que le Route Model Binding fonctionne correctement.

Maintenant, en cliquant sur le lien "En savoir plus" sur la page de la liste, vous accéderez à la page détaillée d'une planète spécifique.


Quiz de consolidation

1. Quelle approche est la meilleure pratique pour séparer la logique de l'API et des pages web ?

2. Que fait return view('planets.index', ['planets' => $planets]);?

3. Qu'est-ce que le Route Model Binding dans le contexte de `show(Planet $planet)` ?

4. Comment formater une date à partir du champ `created_at` dans Blade ?

5. Si la route spécifie `/posts/{post}`, comment doit se présenter la signature de la méthode dans le contrôleur pour que le Route Model Binding fonctionne ?


🚀 Résumé du chapitre :

Vous avez réussi à créer une "vitrine" pour votre API en utilisant l'architecture Laravel MVC. Vous avez maintenant :

  • Un contrôleur séparé pour la logique des pages web.
  • Une page dynamique avec la liste de toutes les planètes, récupérant les données de la base de données.
  • Une page détaillée pour chaque planète utilisant le Route Model Binding.
  • Deux routes web dans routes/web.php pour accéder à ces pages.

Vous avez transformé des données brutes en informations claires et utiles pour l'utilisateur. Dans le chapitre suivant, nous ajouterons de l'interactivité en intégrant du JavaScript dans nos vues Blade pour interagir avec l'API sans recharger la page.