Article publié le 24 juillet 2020 sur mon ancien blog, republié ici tel quel. Les versions et les syntaxes évoquées sont celles de l’époque ; seules les fautes de frappe ont été corrigées. Les captures d’écran d’origine n’ont pas pu être récupérées.

Bonjour à tous et bienvenue sur ce tutoriel ! Aujourd’hui nous allons créer ensemble un CRUD sous Laravel 7.

Qu’est ce qu’un CRUD ?

L’acronyme informatique anglais CRUD (pour createreadupdatedelete) désigne les quatre opérations de base pour la persistance des données, en particulier le stockage d’informations en base de données.

Soit :

  • create : créer
  • read : lire
  • update : mettre à jour
  • delete : supprimer

Création d’un projet

Pour la création de ce CRUD nous allons faire un petit projet très simple qui consiste à créer un panneau de tâches.

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

Voici ce à quoi devrait ressembler votre projet

Capture d’écran absente de l’archive.

Maintenant nous allons créer une base de données et la relier au projet.

Ouvrez MySQL

CREATE DATABASE task;

Afin que votre utilisateur puisse avoir les accès nous allons lui accorder les droits sur la base de données.

GRANT all privileges ON task.* TO 'alex'@'localhost';

Ensuite placez vous dans le projet que vous venez de créer. Puis lancez votre serveur.

cd Documents/Task
php artisan serve

Une fois votre base de données créée nous allons la configurer dans le projet Laravel. Pour cela ouvrez le fichier .env situé à la racine de votre projet.

Vous allez modifier les champs DB_DATABASE, DB_USERNAME, DB_PASSWORD.

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:Uq7TIMofQFIertEt1R7fHebAzn064p+VXvKnSbdrV90=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=task
DB_USERNAME=[VOTRE USER]
DB_PASSWORD=[VOTRE MDP]

BROADCAST_DRIVE

Nous allons maintenant vérifier que les modifications ont bien fonctionné.

Si ce message apparaît c’est que tout est bon !

  Task php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.03 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.02 seconds)

Création du CRUD

Tout d’abord nous allons créer un fichier de migration, qui va permettre de créer la table Task.

  Task php artisan make:migration create_tasks_table 
Created Migration: 2020_07_24_095204_create_tasks_table

Ensuite dans votre éditeur de code ouvrez le fichier [date]_create_tasks_table.php qui se situe dans le répertoire database -> migrations

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

Nous allons donc maintenant ajouter les champs que nous allons utiliser pour ce projet. Pour nos tâches imaginons qu’elles aient un nom et une description.

    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('description');
            $table->timestamps();
        });
    }

Maintenant nous allons faire une migration pour ajouter les champs dans notre base de données.

  Task php artisan migrate
Migrating: 2020_07_24_095204_create_tasks_table
Migrated:  2020_07_24_095204_create_tasks_table (0.02 seconds)
  Task 

Nous allons maintenant créer un Controller et un Model. Vous pouvez le faire en une ligne ou deux, voici deux exemples :

  Task php artisan make:model Task
  Task php artisan make:controller TasksController --resource
  Task php artisan make:controller TasksController --model=Task

Nous verrons très vite ce que signifie --resource.

Nous allons dans un premier temps travailler sur le Model puis sur le Controller.

Votre Model se situe dans le répertoire app, vous trouverez un fichier Task.php.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    //
    
}

Nous allons à présent modifier le fichier pour renseigner les champs que nous avons créés dans la migration de tout à l’heure.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    //
    protected $fillable = ['name', 'description'];
}

Et c’est tout pour le model, plutôt rapide non ?

Nous allons maintenant travailler sur le Controller qui se situe dans le répertoire app->Http->Controllers. Éditez le fichier TasksController.php Vous pouvez constater que le fichier est déjà pré-rempli avec plusieurs fonctions, tout ceci est dû grâce à notre fameux --resource. Plutôt pratique ?

<?php

namespace App\Http\Controllers;

use App\Task;
use Illuminate\Http\Request;

class TasksController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Task  $task
     * @return \Illuminate\Http\Response
     */
    public function show(Task $task)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Task  $task
     * @return \Illuminate\Http\Response
     */
    public function edit(Task $task)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Task  $task
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Task $task)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Task  $task
     * @return \Illuminate\Http\Response
     */
    public function destroy(Task $task)
    {
        //
    }
}

Création des views

Pour commencer nous allons coder la création de tâches.

Laissons de côté le Controller quelques instants.

Dans un premier temps créez un dossier dans resources->view que vous nommerez layout, vous y ajouterez un fichier nommé master.blade.php

<!doctype html>
<html lang="en">
  <head>
    <title>Laravel</title>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  </head>
  <body>
    @yield('content')
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </body>
</html>

Ensuite créez trois fichiers task.blade.php | create.blade.php | edit.blade.php dans votre dossier resources->view.

Ces fichiers seront nos vues où nous pourront respectivement afficher, ajouter, modifier et supprimer nos tâches.

Nous allons faire un affichage très simple pour afficher nos tâches.

Dans notre fichier task.blade.php nous allons créer une page pour afficher les tâches

@extends('layout.master')

@section('content')
<div class="container mt-5">
    <div class="card" style="width: 18rem;">
        <div class="card-body">
          <h5 class="card-title">Titre Tâche</h5>
          <p class="card-text">Description de la tâche</p>
        </div>
      </div>
</div>
@endsection

Dans votre dossier routes ouvrez le fichier web.php et ajoutez y ces trois lignes :

Route::get('tasks', 'TasksController@index')->name('tasks');

Route::get('tasks/create', 'TasksController@create');

Route::get('tasks/edit', 'TasksController@edit');

Vulgairement les routes permettent de relier les urls vers des actions, par exemple un affichage de vue. Essayez dans un premier temps d’entrer http://127.0.0.1:8001/tasks dans votre navigateur. La route va traiter la demande sur l’url tasks et appeler la fonction index de votre controller TasksController.

Actuellement la fonction index ne fait rien.

Rajoutons ceci dans la fonction

    public function index()
    {
        return view('task');
    }

Retournez sur l’url vous pouvez dès à présent voir votre titre sur la page.

Vous devriez voir cet affichage.

Capture d’écran absente de l’archive.

Création d’une tâche

Voici un affichage pour le formulaire de création et modification que vous pouvez réutiliser.

create.blade.php

@extends('layout.master')

@section('content')
<div class="container mt-5">
    <form method="POST" action="{{ url('tasks/create') }}">
@csrf
        <div class="form-group">
          <label>Titre de la tâche</label>
          <input type="text" class="form-control" name="name">
        </div>
        <div class="form-group">
          <label>Description de la tâche</label>
          <textarea rows="4" class="form-control" name="description"></textarea>
        </div>
        <button type="submit" class="btn btn-primary float-right">Submit</button>
    </form>
</div>

@endsection

Allons dans TasksController.php

    public function create()
    {
        return view('create');
    }

    public function store()
    {
            $attributes = request()->validate([
                'name'=>'required',
                'description'=>'required',
            ]);
            $tasks = Task::create($attributes);
            return redirect()->route('tasks');
    }

Rajoutez dans votre fichier route web.php la route correspondante à votre fonction store.

Route::post('tasks/create', 'TasksController@store');

Nous allons maintenant afficher nos tâches dans notre fichier task.blade.php

@extends('layout.master')

@section('content')
<div class="container mt-5">
    <div class="row">
        @foreach ($tasks as $task)
        <div class="col-sm-4">
            <div class="card mt-5 mb-5" style="width: 18rem;">
                <div class="card-body">
                  <h5 class="card-title text-center">{{ $task->name }}</h5>
                  <p class="card-text">{{ $task->description }}</p>
                </div>
              </div>
            </div>
        @endforeach
    </div>
</div>
@endsection

TasksController.php

    public function index()
    {
        $tasks = Task::get()->all();
        return view('task', compact('tasks'));
    }

Vous devriez avoir maintenant votre tâche de créée et d’affichée.

Capture d’écran absente de l’archive.

Modification des tâches

Nous allons maintenant modifier cette tâche.

Pour modifier nos tâches il va nous falloir notre vue edit.blade.php.

@extends('layout.master')

@section('content')
<div class="container mt-5">
    <form>
        <div class="form-group">
          <label>Titre de la tâche</label>
          <input type="text" class="form-control" name="name" value="Ceci sera notre titre">
        </div>
        <div class="form-group">
          <label>Description de la tâche</label>
          <textarea rows="4" class="form-control" name="description">Ceci sera notre description</textarea>
        </div>
        <button type="submit" class="btn btn-primary float-right">Submit</button>
    </form>
</div>

@endsection

Mais un problème se pose, quand nous allons modifier nos vues nous ne voulons modifier que celle sélectionnée. Il faudra donc bien prendre l’id de la tâche.

Modifions notre fichier task.blade.php

@extends('layout.master')

@section('content')
<div class="container mt-5">
    <div class="text-center"><a class="btn btn-primary mt-4" href="{{ url('tasks/create') }}" >Créer une tâche</a></div>
    <div class="row">
        @foreach ($tasks as $task)
        <div class="col-sm-4">
            <div class="card mt-5 mb-5" style="width: 18rem;">
                <div class="card-body">
                  <h5 class="card-title text-center">{{ $task->name }}</h5>
                  <p class="card-text">{{ $task->description }}</p>
                  <a class="btn btn-primary float-right mt-4" href="{{ url('tasks/edit/'.$task->id) }}" >Modifier</a>
                </div>
              </div>
            </div>
        @endforeach
    </div>
</div>
@endsection

Nous venons de rajouter un bouton qui appellera la vue edit.blade.php en y integrant l’id de la tâche dans l’url. Il faut à présent modifier les routes.

Route::get('tasks', 'TasksController@index')->name('tasks');
Route::get('tasks/create', 'TasksController@create');
Route::post('tasks/create', 'TasksController@store');

Route::get('tasks/edit/{id}', 'TasksController@edit');
Route::post('tasks/edit/{id}', 'TasksController@update');

Modifions notre controller.

    public function edit($id)
    {
        $tasks = Task::findOrFail($id);
        return view ('edit', compact('tasks'));
    }

    public function update($id)
    {
        $attributes = request()->validate([
            'name'=>'required',
            'description'=>'required',
        ]);
        $tasks = Task::findOrFail($id);
        $tasks->update($attributes);
        return redirect()->route('tasks');
    }

Dans la fonction edit() nous avons retourné l’id, le controller doit valider l’id de la tâche sinon la fonction échouera. Dans la fonction update nous avons entré les champs qui sont requis pour la modification, l’id ne doit pas changer on le revérifie encore.

Nous pouvons modifier notre fichier edit.blade.php afin de l’adapter à nos changements.

@extends('layout.master')

@section('content')
<div class="container mt-5">
    <form method="POST" action="{{ url('tasks/edit/'.$tasks->id) }}">
        @csrf
        <div class="form-group">
          <label>Titre de la tâche</label>
          <input type="text" class="form-control" name="name" value="{{ $tasks->name }}">
        </div>
        <div class="form-group">
          <label>Description de la tâche</label>
          <textarea rows="4" class="form-control" name="description">{{ $tasks->description }}</textarea>
        </div>
        <button type="submit" class="btn btn-primary float-right">Submit</button>
    </form>
</div>

@endsection

Capture d’écran absente de l’archive.

Capture d’écran absente de l’archive.

Suppression des tâches

Nous allons maintenant ajouter la possibilité de supprimer les tâches. Dans un premier temps modifions le fichier edit.blade.php pour ajouter un bouton qui supprimera la tâche.

@extends('layout.master')

@section('content')
<div class="container mt-5">
    <form method="POST" action="{{ url('tasks/edit/'.$tasks->id) }}">
        @csrf
        <div class="form-group">
          <label>Titre de la tâche</label>
          <input type="text" class="form-control" name="name" value="{{ $tasks->name }}">
        </div>
        <div class="form-group">
          <label>Description de la tâche</label>
          <textarea rows="4" class="form-control" name="description">{{ $tasks->description }}</textarea>
        </div>
        <button type="submit" class="btn btn-primary float-right">Submit</button>
    </form>
    <form action="{{ url('tasks/delete/'.$tasks->id) }}" method="POST">
        @csrf
        @method('DELETE')
            <button class="btn btn-danger mb-4 mr-4 float-right" type="submit">Supprimer</button>
    </form>
</div>

@endsection

N’oublions pas de créer la route que nous venons d’entrer dans le formulaire.

Route::get('tasks', 'TasksController@index')->name('tasks');
Route::get('tasks/create', 'TasksController@create');
Route::post('tasks/create', 'TasksController@store');

Route::get('tasks/edit/{id}', 'TasksController@edit');
Route::post('tasks/edit/{id}', 'TasksController@update');
Route::delete('tasks/delete/{id}', 'TasksController@destroy');

Pour terminer nous completons la fonction destroy() dans notre controller.

    public function destroy($id)
    {
        //
        $task = Task::findOrFail($id);
        $task->delete();
        return redirect()->route('tasks');
    }

Voilà vous pouvez supprimer la tâche que vous avez sélectionnée.

Merci d’avoir suivi ce tutoriel, n’hésitez pas à interagir dans les commentaires !