Laravel : transférer et afficher une image

Bonjour, tout au long de ce projet, vous apprendrez à transférer un fichier dans votre dossier d’application Laravel. Nous verrons également comment valider le fichier et l’enregistrer dans une base de données MySQL. Ce tutoriel vous aidera à comprendre pas à pas le concept de transfert et de validation de fichiers avec Laravel.

Pré-requis

  • Un serveur LAMP tel que Laragon, WAMP ou XAMP, dans ce projet j’utilise Laragon
  • Un client MySQL comme PHPMyAdmin ou HeidiSQL, dans ce projet j’utiliserais MySQL Workbench
  • Un éditeur de code, dans ce projet j’utiliserais Visual Studio Code
  • Les bases de Laravel

Créer une application Laravel

Commençons par créer une application Laravel :

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

Connecter votre application avec votre base de données

1. Commencer par créer une base de données dans MySQL
2. Mettez à jour le fichier .env :

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=marvel
DB_USERNAME=root
DB_PASSWORD=

Créer un modèle et exécuter les migrations

1.  Générer un modèle avec l’option -m pour ajouter le fichier de migration :

php artisan make:model Hero -m

2. Définissez les valeurs de la table hero dans database/migrations/xxxxx_create_heros_table.php. Nous ajoutons un nom et le lien de l’image :

    public function up()
    {
        Schema::create('heroes', function (Blueprint $table) {
            $table->id();
            $table->string("name");
            $table->string("image");
            $table->timestamps();
        });
    }

3. Ajoutez les propriétés dans le fichier modèle Hero.php :

class Hero extends Model
{
    use HasFactory;
    protected $fillable = ['name' , 'image']; 
}

4. Dans la console, exécutez la migration :

php artisan migrate

Créer et configurer le contrôleur

Maintenant nous devons créer un contrôleur pour pouvoir envoyer et afficher une image à travers la vue.

1. Ajouter le contrôleur :

php artisan make:controller HeroController

2. Dans le fichier HeroController nous allons importer la model Hero et ajouter 3 functions :

<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Hero;

class HeroController extends Controller
{
  // Affiche la liste des personnages
  public function index() {
    
  }
  
  // Affiche le formulaire
  public function create() {
    
  }
  
  // Enregistre les données du formulaire dans la base de données
  public function store(Request $request) {
  
  }
}

Ajouter les routes

Ensuite nous définissons les routes dans le fichier web.php :

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HeroController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
// Affiche la liste des personnages
Route::get('/', [HeroController::class, 'index'])->name('index');

// Affiche le formulaire
Route::get('create-hero', [HeroController::class, 'create']);

// Enregistre les données du formulaire dans la base de données
Route::post('store-hero', [HeroController::class, 'store'])->name('store-hero');

Notez à la ligne 17, nous supprimons la redirection Welcome par la méthode index.

Afficher le formulaire

C’est parti ! Commençons par créer le formulaire.


1. Retournons dans le controller HeroController, dans la function create() retournez la view create :

  // Affiche le formulaire
  public function create() {
    return view('create');
  }

2. Puis dans le dossier views, ajoutons le fichier de template create.blade.php et son contenu :

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
  <title>Ajouter un héro</title>
</head>
<body>
  
  <div class="container">
    <div class="row justify-content-center pt-md-5">
        <div class="col-md-6">
          <h2 class="pb-md-4">Ajouter un personnage</h2>
            <div class="card box-shadow">
                  <div class="card-body">
                     <form method="POST" action="{{route('store-hero')}}" enctype="multipart/form-data">
                      @csrf
                      <div class="form-group mb-3">
                        <label>Nom</label>
                        <input type="text" name="name" class="form-control" />
                      </div>
                      <div class="form-group mb-3">
                        <label>Image</label>
                        <input type="file" name="image" class="form-control" />
                      </div>
                      <div class="form-group mb-3">
                        <button type="submit" class="btn btn-primary">Ajouter</button>
                        <a href="/">Retour</a>
                      </div>
                    </form>

                </div>
            </div>
        </div>
    </div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>

Remarquez à la ligne 18, pour l’attribut action nous avons mis le nom de la route store-hero et un nouveau attribut qui est enctype="multipart/form-data".
Vous devez utiliser multipart/form-data lorsque votre formulaire comprend des balises <input type=’file’> (ligne 26).

3. Maintenant testons le formulaire, nous devons démarrer le serveur : php artisan serve et lançons un navigateur avec l’adresse http://127.0.0.1:8000/create-hero :

Formulaire pour ajouter un personnage
Formulaire pour ajouter un personnage

Bravo le formulaire est crée ? !.

Enregistrer dans la base de données

1. Tout d’abord ajouter dans le dossier public, un nouveau dossier nommé images

2. Ensuite retournons sur HeroController et mettons à jour la function store() :

 // Enregistre les données du formulaire dans la base de données
  public function store(Request $request) {
    $request->validate(
      ['image' => 'required|mimes:png,jpg,jpeg,gif']
    );

    $newHero = new Hero;
    $imageName = time() . '.' . $request->image->extension();  
    $request->image->move(public_path('images'), $imageName);

    $newHero->name = $request->name;
    $newHero->image = '/images/' . $imageName;
    $newHero->save();

    return redirect()->route('index')
                     ->with('success','Personnage ajouté avec succcès.');
  }
  • Ligne 22 : dans la méthode validate(), nous acceptons uniquement les extensions d’images.
  • Ligne 26 : nous ajoutons une variable $imageName qui vaut l’heure et l’extension de l’image transféré.
  • Ligne 27 : avec la méthode move(), nous demandons à ce que l’image soit placé dans le dossier public/images et le fichier sera renommé par la valeur de la variable $imageName.
  • Ligne 33 : Si l’enregistrement est un succès, nous sommes redirigé vers la page d’accueil avec un message.

3. Testons notre formulaire ! Donnez un nom et ajoutez une image, vous pouvez télécharger cette image de Superman, puis cliquez sur le bouton Ajouter.

Formulaire pour ajouter un personnage
Formulaire pour ajouter un personnage

Normalement vous arrivez sur un écran vide ! C’est normal nous n’avons pas encore écris le contenu de la view index. Cependant dans le dossier public/images vous aurez le fichier d’image :

repertoire-images
Répertoire du dossier public/images

Et dans la base de données, le fiche du personnage ajouté :

Résultat table Hero
Résultat de la table Hero

Parfait ! L’enregistrement fonctionne !

Afficher la liste avec les images

1. Retournons dans le controller HeroController. Dans la function index(), nous ajoutons une nouvelle variable pour stocker le contenu de la table Hero, puis nous envoyons la variable dans le view index :

  // Affiche la liste des personnages
  public function index() {
    $heros = Hero::all();
    return view('index', compact('heros'));
  }

2. Dans le dossier views, ajouter un nouveau fichier et nommé le index.blade.php. Puis ajoutez ce contenu :

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
  <title>Ajouter un héro</title>
</head>
<body>
  
  <div class="container">
    <div class="px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
      <h2 class="pb-md-4">Les super-héros !</h2>
    </div>
    <div class="row">
      @foreach($heros as $hero)
      <div class="card mr-4" style="width: 15rem;">
        <img class="card-img-top p-3" src="{{$hero->image}}" alt="Card image cap">
        <div class="card-body">
          <h5 class="card-title">{{$hero->name}}</h5>
        </div>
      </div>
      @endforeach
    </div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>

Notez à la ligne 17, nous avons mis une boucle sur la variable heros, puis nous ajoutons les variables pour l’url de l’image (ligne 19) et le nom (ligne 21).

3. Sauvegardez et afficher l’index du site : http://127.0.0.1:8000/

Page d'accueil avec la liste des héros
Page d’accueil avec la liste des héros

Félicitations vous avez réussi ?? !.

Conclusion

Nous avons terminé notre projet. Nous avons vu comment accepter uniquement les fichiers images et transférer l’image dans le dossier de l’application. Nous avons aussi enregistré les données dans la base de données MySQL. J’espère que vous avez aimé ce projet. Excellente journée à vous et à bientôt ?.

Leave a Comment