Catégories
Dev

Premier projet MVC en laravel 8

Je vais essayer de vous expliquer ce qu’est un MVC et je vous proposerais de créer un site rapidement pour utiliser le MVC dans Laravel 8.

Avant toute chose, il faut installer Laravel sur votre ordinateur. Si vous ne savez pas comment faire vous pouvez lire cet article qui vous expliquera en détail comment procéder : https://oursblanc.tech/dev/installer-un-nouveau-site-laravel-8/.

Maintenant que vous avez laravel, tout est prêt pour commencer notre développement. Mais pour ça, il faut encore bien comprendre ce qu’est un MVC et comment il fonctionne.

C’est quoi un MVC ?

MVC signifie Modèle Vue Controller. C’est une manière de programmer qui permettra d’avoir un programme propre et lisible par n’importe quel autre développeur.

Modèle

C’est avec le modèle que vous allez traiter les données de votre base de données. Il va transformer ce que contient votre base en objets qui pourront ensuite être manipulé par le controller.

Controller

Le controller va s’occuper de toute la partie complexe du site. Il va utiliser les objets que le modèle lui envoie pour les afficher sur la vue en fonction des besoins de l’utilisateur. Il y aura toutes les fonctions de notre site dedans (index, create, update…). C’est le cerveau du site, c’est ici que se trouve toute l’intelligence du site.

Vue

La vue est ce que l’utilisateur d’internet va voir sur son écran. Elle se contente d’afficher une page HTML avec les informations que lui envoie le controller.

Vous connaissez maintenant les grandes lignes du MVC. Je vous propose donc de créer ensemble notre premier projet Laravel. Je ferais à titre d’exemple un site qui liste des films et dans lequel on pourra voir un détail de chaque films, les triers par catégorie, les supprimer de la liste ou encore en ajouter. Cet exemple permettra de voir les bases du MVC.

Installation du projet

Nous allons utiliser le terminal pour créer le projet. D’abord déplacez vous dans le répertoire où votre futur projet devra se trouver :

cd nomDuRepertoire

Puis créez votre projet avec cette commande :

composer create-project --prefer-dist laravel/laravel MVCLaravel

Après quelques secondes, ça y est ! Votre environnement laravel est créé.

Il faut encore configurer un URL pour pouvoir tester notre programme au fur et à mesure avec cette commande :

valet link mvclaravel

Attention ! Si la commande ne fonctionne pas, c’est probablement que vous ne vous trouvez pas dans le bon répertoire. Vérifiez que vous êtes bien dans le répertoire de votre projet.

Il ne nous reste plus qu’à sécuriser cet URL de la manière suivante :

valet secure mvclaravel

Pour vérifier que tout est bon, tapez mvclaravel.test dans la barre d’URL. Si tout est bon, une page Laravel devrait apparaître.

Si ça fonctionne c’est que tout est prêt, et nous pouvons commencer.

La base de donnée

Etant donné que nous utiliserons une base de donnée, la première chose à faire est de la créer.

Nous allons donc créer une base de donnée « films » qui contient la table « films ». Dans cette table il doit y avoir une colonne « id », une colonne « affiche », une colonne « titre », une colonne « genre », une colonne « description », une colonne « created_at » et enfin, une colonne « updated_at » comme ceci :

Je vous laisse remplir la table et vous conseille au moins 2 films de chaque genre. Pour les affiches, je vous conseil de mettre le nom.jpeg et de mettre toutes les images dans un dossier « images » que vous pourrez placer dans le dossier public.

Ensuite, allez dans le fichier « .env ». Vous trouverez à partir de la ligne 10 les informations de connection à la base de donnée. A la ligne 13 à « DB_DATABASE=laravel » remplacez « laravel » par le nom de votre base de donnée. Si vous avez mis un mot de passe a votre base de donnée ou si vous avez modifié le port par exemple, c’est dans ce fichier qu’il faudra renseigner ces différentes informations.

Mise en place du MVC

Je vous propose maintenant de créer un controller à partir du terminal que l’on appellera FilmController :

php artisan make:controller FilmController

Il se trouve désormais dans app/Http/Controllers.

De la même façon, créez maintenant un modèle :

php artisan make:model Film

Vous le trouverez dans app/Models.

Nous avons créer le modèle et le controller, il nous manque donc la vue que vous pouvez créer dans le dossier ressources/views dans un sous-répertoire film en l’appelant index.blade.php . Vous remarquerez que les vues dans Laravel sont des fichiers .blade.php, ils ont une syntaxe particulière que vous pourrez voir plus tard dans le projet.

Je vous invite à télécharger Bootstrap et à le placer dans le dossier « public » sous le nom de « bootstrap ». Si vous ne voulez pas le télécharger vous pouvez utiliser son CDN. Même chose pour jQuery.

Création d’un projet complet en Laravel 8.0

Nous avons désormais tous les composants de notre MVC. Cependant, il faut que nous configurions des routes car sans ça, la seule page que nous verrons est la belle page d’accueil de Laravel.

Je vous invite donc à aller dans le fichier web.php qui se trouve dans le dossier routes. A l’intérieur, vous pouvez écrire :

Route::resource('/films/', '\App\Http\Controllers\FilmController');

Qu’est ce que cette ligne signifie?

  • Route::resource va créer automatiquement les routes pour les fonctions principales d’un site : CRUD ( un article dédié au crud suis celui-ci ).
  • ('/films/', indique que le mot principal de notre URL sera ‘films’. Il se retrouvera dans tous nos URL.
  • '\App\Http\Controllers\FilmController') est l’action. Ca indique au programme ce qu’il doit faire si l’url contient ‘/films/‘. Ici, nous appelons la classe FilmController. L’action que le programme va effectuer va varier suivant ce qui se trouve derrière ‘films/’. Cette action sera définie par les fonctions du controller.

Vous pouvez consulter toutes vos routes grâce au terminal en tapant :

php artisan route:list

Si nous n’avions pas utiliser ressource, notre route aurait ressemblé à ça :

Route::get('/films/', '\App\Http\Controllers\FilmController@index');

Nous aurions du faire une route pour chaque fonction de notre controller.

Bref, pour que cette route ne soit pas inutile, nous allons donc commencer à écrire dans le Controller en créant cette fonction « index ». Vous pouvez donc écrire ceci :

public function index(){
    $films = \App\Models\Film::all();
    return view('index', compact('films');
}

Ici, nous définissons la fonction index de notre Controller.

  • \App\Models\Film indique au programme qu’il doit utiliser le modèle Film. Voyez le model comme étant l’objet représentant notre base de donnée.
  • ::all() est une manière de faire un SELECT * FROM. Les modèles Laravel utilisent Eloquent, un constructeur de requête, avec une syntaxe assez particulière.
  • return view('index', on dit à la fonction de nous afficher la vue index ( index.blade.php )
  • compact('films'); va permettre à la vue d’utiliser la variable $films.

Pour vérifier que ce code marche, mettons dans la vue :

@foreach($films as $film)
    <p>{{$film->id}} : {{$film->titre}}<br/></p>
@endforeach
  • {{$film->id}} est l’équivalent de <?php echo($film['id'] ?>
  • pour chaque structures conditionnelles ou chaque boucles, blade à besoin d’un @… et pour clore @end… . Ceci vaut donc pour les for, while, if, etc…

C’est la syntaxe de blade.

Pour ceux que ne l’auraient toujours pas fais, vous pouvez maintenant recharger votre page et vous devriez avoir une liste de tous vos films.

Mise en place d’un layout

Nous aurons plus tard plusieurs vues, et pour rendre notre code plus propre, nous allons créer un layout. Dans le répertoire views, vous avez déjà un sous répertoire film si vous avez fais comme moi. Vous allez pouvoir en créer un nouveau et le nommer layouts. Créez à l’intérieur de ce dernier une vue page.blade.php que je vous laisse compléter comme ci dessous :

<!DOCTYPE html>
<html lang="fr">
<head>
    
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@yield("title") | Projet MVC</title>

    <link rel="stylesheet" href="\bootstrap\css\boostrap.css">
    @yield("css")

</head>
<body>

    <h1>Mon layout</h2>
    <div class="container">
        @yield("content")
    </div>
    @yield("js")

</body>
</html>

Vous retrouvez ici la structure de base HTML (pour les utilisateurs de VS Code : tapez ! puis tab/entré pour avoir la structure grâce à Emmet) et des @yield(). @yield indique un endroit ou l’on va mettre du contenu. Ceci nous permettra d’avoir une seule et même structure de page pour plusieurs vues tout en modifiant le contenu. Pour que ça fonctionne, allez changer votre page vue comme ceci :

@extends("layouts.page")
@section("title")
    Liste des films
@endsection
@section("content")
    <h2>Ma liste de films</h2>
    <div class="row">
        <div class="col">
            @foreach($films as $film)
                <p>{{$film->id}} : {{$film->titre}}<br/></p>
            @endforeach
        </div>
    </div>
@ensection

Maintenant que c’est fait, vous aurez peut être compris comment fonctionne le layout. Tout ce qui se trouve entre @section et @endsection va se retrouver là où le @yield qui correspond se situe. Vous pouvez constater cet exemple avec @yield("title") qui va contenir ce qui se trouve entre @section("title") et @endsection ou encore @yield("content") qui contiendra ce qui se trouve entre @section("content") et @endsection.

La vue « index », notre page d’accueil

Une fois que vous avez compris ça, on peux donc continuer et donner un peux de forme à ce site. Je vous invite donc à modifier index de cette façon :

@extends("layouts.page")
@section("title")Liste des films @endsection
@section("recherche")
    <form class="form-inline my-2 my-lg-0" method="GET" >
        <input class="form-control mr-sm-2" type="search" placeholder="Recherche" name="recherche" aria-label="Search">
        <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Trouver</button>
    </form>
@endsection
@section("content")
<div class="row">
        <div class="col">
            <table class="table">
                    <thead class="thead-dark">
                        <tr>
                            <th scope="col">#</th>
                            <th scope="col">Affiche</th>
                            <th scope="col">Titre</th>
                            <th scope="col">Genre</th>
                        </tr>
                    </thead>

                @foreach($films as $film)
                    <tbody>
                        <tr>
                            <th scope="row">{{$film->id}}</th>
                            <td><a href="/films/{{$film->id}}/"><img src="\images\{{$film->affiche}}" alt="affiche de {{$film->titre}}" style="width: 200px"></a></td>
                            <td><a href="/films/{{$film->id}}/">{{$film->titre}}</a></td>
                            <td>{{$film->genre}}</td>
                        </tr>
                    </tbody>
                @endforeach

            </table>
        </div>
    </div>
@endsection

Je ne vais pas rentrer dans le détail pour la mise en forme. Je vous laisse donc copier mon code pour le récupérer si vous le voulez ( à mettre dans layouts/page.blade.php ) :

<!DOCTYPE html>
<html lang="en">
<head>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@yield("title") | Projet MVC</title>
    
    <link rel="stylesheet" href="\bootstrap\css\bootstrap.css">
    <style>
        body {
            background-color: #f8f9fa;
        }

        .navbar {
            background-color: #f8f9fa;
            max-height: 56px;
        }

        a {
            text-decoration: none;
            color: black;
            font-size: 1em;
            transition: 0.250s cubic-bezier(0,-0.44, 0.96, 1.41);
        }
        a:hover {
            color: black;
            font-size: 1.1em;
            text-decoration: none;
            font-weight: bolder;
        }

    </style>
        @yield("css")

</head>

<body>
<div class="container">
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav mr-auto">
                <li class="nav-item active">
                    <a class="nav-link" href="/films/">Accueil <span class="sr-only">(current)</span></a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        Actions
                    </a>
                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <a class="dropdown-item" href="#">Ajouter un film</a>
                        <a class="dropdown-item" href="#">Modifier un film</a>
                        <div class="dropdown-divider"></div>
                        <a class="dropdown-item" href="#">Supprimer un film</a>
                    </div>
                </li>
            </ul>
            @yield("recherche")
        </div>
    </nav>
    
        @yield("content")
    </div>

    <script src="\jQuery.js"></script>
    <script src="\bootstrap\js\bootstrap.js"></script>
    @yield("js")
</body>

</html>

Vous aurez surement remarquer la présence d’une zone de recherche dans la barre de navigation. Nous allons donc la rendre opérationnelle en modifiant notre controller comme ceci:

    public function index(Request $request) {
        
        $strRecherche = $request->input("recherche");
        if($strRecherche == "") {
            $films = \App\Models\Film::all();
        } else {
            $films = \App\Models\Film::where("titre","like","%".$strRecherche."%")->get();
        }
        
        return view('film.index', compact('films'));
    
    }

Nous venons de dire à notre controller que si il y a quelque chose dans la barre de recherche, alors $films ( la variable qui va s’afficher sur index ) aura tous les titres qui contiennent cette chaîne de caractère. Sinon, $film contient tous les films de notre base. Nous pouvons bien évidement effectuer une recherche sur les genres ou même les genre et les titre en même temps, mais nous ferrons ça plus tard. La recherche est donc maintenant fonctionnelle sur votre site.

La deuxième page de notre site : une vue détaillé sur chaque films

Passons maintenant aux détails. Nous allons créer une page qui nous permettra de visualiser en détail un film. Avant de créer la vue, il faut faire le controller. On va donc pourvoir rajouter une nouvelle fonction « show » :

    public function show(\App\Models\Film $film, Request $request) {

        $autreGenre = \App\Models\Film::where("genre", "!=", $film->genre)->distinct()->get(["genre"]); 
        $filmsMemeGenre = \App\Models\Film::where("genre", "=", $film->genre)->where("id", "!=", $film->id)->get();

        return view('film.details', compact("autreGenre", "film", "filmsMemeGenre"));

    }
  • \App\Models\Film $film est un paramètre que l’on donne à la fonction, tout comme Request $request

Vous pouvez maintenant créer une nouvelle vue « details.blade.php ». Je vous met ma page détail, mais bien évidement vous pouvez la présenter autrement. Faites juste attention a ne pas oublier les @ pour les sections et les @endsection.

@extends("layouts.page")
@section("title")
    {{$film->titre}}
@endsection
@section("css")
    <style>
        .imageDetails {
            width: 225px;
        }
        .footer {
            border-top: 2px solid grey;
        }
        h1 {
            background-color: #343a40;
            color: #fff;

            padding: 0.75rem;
            line-height: 1.5;

            font-size: 1.75rem;
            font-weight: bold;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
        }
        ul {
            padding: none;

        }
        ul li{
            list-style-type: none;
        }
        .contenu {
            height: 400px;
            margin-top: 10px;
            margin-bottom: 10px;
        }
        .bouton {
            position: relative;
            left: 350px;
            top: 95px;
        }
    </style>
@endsection

@section("content")
<h1>{{$film->titre}}</h1>
<div class="row contenu">
    <div class="col-4">
        <img src="\images\{{$film->affiche}}" alt="Affiche de {{$film->titre}}" class="imageDetails">
    </div>
    <div class="col-8">
        <h4>Résumé :</h4>
        <p>{{$film->description}}</p>
    </div>
</div>
<div class="row footer">
    <div class="col">
        <p>Dans le genre {{$film->genre}}, vous pourriez aimer</p>
        <ul>
            @foreach($filmsMemeGenre as $gfilm)
                    <li><a href="https://mvclaravel.test/films/{{$gfilm->id}}/">{{$gfilm->titre}}</a></li>
            @endforeach
        </ul>
    </div>

    <div class="col">
        <a href="https://mvclaravel.test/films/" class="bouton"><button type="button" class="btn btn-primary">Retour à l'accueil</button></a>
    </div>
</div>
@endsection

Pour finir, il faut un URL pour pouvoir consulter cette vue donc si vous n’avez pas utiliser la méthode resource, dans le fichier des routes web :

Route::get('/films/{film}', '\App\Http\Controllers\FilmController@show');
  • {film} va indiquer au programme quel film il va devoir sélectionner en se référant à l’id.
  • FilmController@show va lui indiquer la fonction show du controller film

Pour ce qui est de l’ajout, modification ou suppression de films de la base de donnée ainsi que de la recherche avancé, je le ferais dans un autre extrait disponible ici.

Le thème principale de ce tuto était le Modèle Vue Controller.

Résumé

Pour résumé ce qu’on à vu, le MVC est une manière de programmer qui simplifie la lecture du code et qui réparti celui-ci en trois grandes partie :

  • Le Model est la partie la plus basse du programme, il communique directement avec la base de donnée et renvoie au Controller les données sous forme d’objets.
  • La Vue est la partie la plus superficielle avec le moins d’intelligence qui se contente d’afficher une page avec ce qu’elle reçoit du Controller.
  • Le Controller est l’intermédiaire entre la Vue et le Modele, il possède la plus grosse partie de l’intelligence du programme.

Dans l’exemple que j’ai fais avec les films, nous n’avons rien écrit dans le Model. Mais pourtant nous l’avons utiliser à plusieurs reprises lorsque nous l’appelions dans le Controller avec \App\Models\Film. Attention ! Ce n’est pas parce que nous avons rien écrit dans le Model qu’il est inutile. Supprimez le et plus rien ne fonctionnera. Laravel a implémenter Eloquent qui rend le système assez intelligent pour faire certaines action tout seul.

Une réponse sur « Premier projet MVC en laravel 8 »

Laisser un commentaire