Vous êtes sur la page 1sur 28

SUPPORT DE COURS

LARAVEL ELOQUENT : COMPRENDRE LES MODELES


ET LEURS RELATIONS

Dans cette partie nous allons parler des modèles qui vous permettent de gérer
vos data dans la base de données. En effet, Laravel inclut Eloquent, un mappeur
objet-relationnel (ORM) qui rend agréable l’interaction avec votre base de
données. Lorsque vous utilisez Eloquent dans Laravel, chaque table de base de
données a un « modèle » correspondant qui est utilisé pour interagir avec cette
table.

En plus de récupérer des enregistrements de la table de la base de données, les


modèles Eloquent vous permettent d’insérer, de mettre à jour et de supprimer
des enregistrements de la table. Vous allez alors pouvoir utiliser des fonctions
directement prévues et gérées par Laravel qui vous permettent de vous simplifier
fortement la vie.

Parallèlement à cela, il y a ce que l’on appelle les relations entre vos modèles. En
effet, une table peut être liée à une autre. Une fois que votre application se
complexifie, vous allez alors avoir plusieurs tables qui seront liées entre elles selon
ce que fait votre application. Une table » commande » sera liée à la table
« produits « , une table » client » sera liée à une table » commandes « , mais aussi
une table » factures » elle-même liée à la table » commandes « . Vous voyez
l’idée ?

Prenons comme exemple le cas d’une application de Blog simple fait avec
Laravel Nous allons voir les migrations correspondantes pour l’exemple et surtout
les modèles ainsi que les relations qui permettent de gérer un blog simple.

Les différents types de relation entre les modèles de


données dans Laravel

hasOne : Cette relation indique qu’un enregistrement dans la table A ne peut


être associé qu’à un seul enregistrement dans la table B. Il s’agit d’une relation
« un à un » entre deux modèles de données. Ainsi la relation hasOne peut être
décrite comme une association de type 1:1. Par exemple :

 Un utilisateur ne peut avoir qu’un seul profil.

 Une voiture n’a qu’une seule plaque d’immatriculation.

 Un commentaire n’a qu’un seul auteur.

hasMany : Cette relation indique qu’un enregistrement dans la table A peut être
associé à plusieurs enregistrements dans la table B. La relation hasMany peut être
décrite comme une association de type 1:n. Par exemple :
 Un article de blog peut avoir plusieurs commentaires.

 Un sondage peu avoir plusieurs propositions.

 Une commande ou un panier peut avoir plusieurs articles.

belongsTo : Cette relation indique qu’un enregistrement dans la table A


appartient à un enregistrement unique dans la table B. La relation belongsTo
peut également être décrite comme une association de type 1:n. Quelques
exemples :

 Un commentaire n’appartient qu’à un seul article.

 Un article n’est écrit que par un seul auteur.

 Une image n’a été upload que par un seul utilisateur.

Pour mieux comprendre la différence entre les deux dernières relations hasMany
et belongsTo. on peut schématiser les choses de la manière suivante :

 La relation hasMany est utilisée lorsqu’un modèle est en relation avec


plusieurs instances d’un autre modèle. Par exemple, un utilisateur peut
avoir plusieurs commentaires, ou une entreprise peut avoir plusieurs
employés. Dans ce cas, le modèle qui a plusieurs instances est considéré
comme le modèle parent et le modèle qui a une seule instance est
considéré comme le modèle enfant. Ainsi, la relation hasMany est définie
dans le modèle parent en utilisant la méthode hasMany.

 La relation belongsTo est utilisée lorsqu’un modèle est en relation avec


une seule instance d’un autre modèle. Donc un commentaire peut être
associé qu’à un seul utilisateur, ou un employé peut être associé qu’à
une seule entreprise. Dans ce cas, le modèle qui a une seule instance est
considéré comme le modèle parent et le modèle qui a plusieurs instances
est considéré comme le modèle enfant. La relation belongsTo est définie
dans le modèle enfant en utilisant la méthode belongs. On peut
considérer que c’est la fonction » inverse » qui vient compléter notre
hasMany que nous venons de voir au dessus.

belongsToMany : Cette nouvelle relation indique qu’un enregistrement dans la


table A peut être associé à plusieurs enregistrements dans la table B, et vice
versa. Cette relation est souvent utilisée pour représenter des relations de type »
many-to-many « . On peut donc aussi indiquer que la relation belongsToMany
peut être décrite comme une association de type n:m. Quelques exemples :

 Plusieurs catégories peuvent être associées à plusieurs articles de blog.

 Des produits peuvent être dans plusieurs commandes.

 Des utilisateurs ont des langages de programmation préférés sur leur


profil.

 Des fables mentionnent des animaux.

hasManyThrough : Cette relation permet de traverser une relation belongsTo


pour récupérer des enregistrements de la table B en passant par la table
intermédiaire C. Avec notre exemple de blog simple mentionné au début, on veut
donc par exemple récupérer tous les commentaires d’un utilisateur. Pour cela on
peut utiliser la relation hasManyThrough en passant par la table des articles. Nous
verrons dans le code juste après comment mettre ça en pratique.

Dit autrement, la relation hasManyThrough peut être décrite comme une


association de type 1:n, mais en passant par une table de plus. Il faut donc
imaginer qu’un enregistrement dans une table A peut être associé à plusieurs
enregistrements dans une table B en passant par une table C.

hasOneThrough : Cette relation est similaire à hasManyThrough, sauf qu’elle


permet de récupérer un enregistrement unique de la table B plutôt que plusieurs
enregistrements. Par exemple, pour récupérer le profil d’un utilisateur en passant
par la table des utilisateurs, on peut utiliser la relation hasOneThrough. Ainsi un
enregistrement dans une table A est associé à exactement un enregistrement
dans une table B en passant par une table C.

Le code pour comprendre les relations entre les modèles dans Laravel

Comme je vous l’ai dit dans l’introduction de cet article, pour illustrer tout ce que
nous venons de voir, je vais illustrer ces différentes relations avec les modèles
via un exemple de blog simple. Dans notre mini blog, il y a donc des articles,
des commentaires sur les articles et enfin des auteurs qui écrivent des
articles et des commentaires. On commence comme d’habitude par créer le
cadre qu’il nous faut pour cela. Dans votre projet Laravel, vous pouvez donc créer
les 3 migrations suivantes :

php artisan make:migration create_articles_table --create=articles

php artisan make:migration create_authors_table --create=authors

php artisan make:migration create_comments_table --create=comments

 Comprendre les migrations dans Laravel pour créer les tables de sa base
de données

Normalement, si vous êtes arrivés ici, c’est que vous connaissez déjà un peu les
migrations. On va maintenant remplir les 3 migrations que nous venons de créer
avec le contenu qui va suivre.

La migration create_articles_table :

<?php

use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;
class create_articles_table extends Migration

public function up()

Schema::create('articles', function (Blueprint $table) {

$table->id();

$table->string('title');

$table->text('body');

$table->timestamps();

});

public function down()

Schema::dropIfExists('articles');

La migration create_authors_table :

<?php

use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;

class create_authors_table extends Migration

public function up()

Schema::create('authors', function (Blueprint $table) {

$table->id();

$table->string('name');
$table->string('email');

$table->timestamps();

});

public function down()

Schema::dropIfExists('authors');

La migration create_comments_table :

<?php

use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;

class create_comments_table extends Migration

public function up()

Schema::create('comments', function (Blueprint $table) {

$table->id();

$table->integer('article_id');

$table->integer('author_id');

$table->text('body');

$table->timestamps();

});

public function down()


{

Schema::dropIfExists('comments');

Maintenant que nous avons le contenu de nos migrations qui est fait, nous
pouvons les jouer avec la commande :

php artisan migrate

Introduction aux modèles de données dans Laravel

Bien évidemment, tout ce qui est décrit dans cet article est donné à titre
d’exemple pour comprendre ce que sont les modèles et leur concept. Si vous
faites un blog, je doute que vous utilisiez cette logique de données, mais je
trouvais l’exemple facile à comprendre pour un nouveau venu dans Laravel et
pour utiliser ce que le framework propose. Il est temps de passer à la partie la plus
intéressante, les modèles de données.

On va donc créer nos 3 modèles correspondants à ce que nous venons de décrire


dans les migrations avec les 3 commandes :

php artisan make:model Article

php artisan make:model Author

php artisan make:model Comment

Commencons par remplir le modèle de données Article, son contenu est alors le
suivant :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Relations\HasMany;

use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Article extends Model

public function comments(): HasMany

return $this->hasMany(Comment::class);
}

public function author(): BelongsTo

return $this->belongsTo(Author::class);

// suite du model

Dans ce modèle Article j’ai volontairement appliqué un typage fort pour respecter
les bonnes pratiques du langage PHP et éviter les problèmes dans le futur. De
plus, cela permet à votre IDE (environnement de développement intégré) de
mieux comprendre ce qu’il se passe.

J’ai également ajouté un use statement pour chaque classe de relation que nous
utilisons dans ce modèle. Cela permet à PHP d’importer automatiquement les
classes nécessaires au moment de l’exécution, ce qui nous évite d’avoir à spécifier
le chemin complet à chaque fois que nous voulons utiliser une classe de relation.

Enfin, concernant le modèle Article en lui-même, j’ai ajouté la mention


comments() avec HasMany car si vous avez bien suivi au début, cette relation
nous indique qu’un article de notre blog peut avoir plusieurs commentaires.
Par contre, j’ai ensuite choisi de définir une relation « belongsTo » vers le modèle
« Author » car un article n’a qu’un seul auteur. Passons au modèle suivant qui
est Comment :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Comment extends Model

public function article(): BelongsTo

return $this->belongsTo(Article::class);
}

public function author(): BelongsTo

return $this->belongsTo(Author::class);

// ...

J’ai donc indiqué avec mes relations belongsTo qu’un commentaire n’appartient
qu’à un seul article, et qu’il ne peut avoir qu’un seul auteur, pratique non ? À
présent, on peut passer au dernier modèle qui permet de compléter le tout.
Notre dernier modèle sera comme vous le devinez Author :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Relations\HasMany;

class Author extends Model

public function articles(): HasMany

return $this->hasMany(Article::class);

public function comments(): HasMany

return $this->hasMany(Comment::class);

}
// suite du model

En conclusion avec ce modèle dans Laravel, on indique via les relations dans
notre modèle de donnée qu’un auteur peut donc avoir plusieurs articles et bien
évidemment plusieurs commentaires. J’espère que ce petit exemple vous sera
utile. Ce n’est pas pour autant terminé, car nous n’avons pas encore vu toutes les
relations. Il nous manque ainsi les relations hasOne et belongsToMany, voyons
voir comment on peut faire pour les introduire dans notre petit projet de blog.

Pour la suite, je ne vais pas vous fournir de migrations et les commandes de


création du modèle, car maintenant, vous savez faire tout ca. On recommence
avec hasOne. Pour l’intégrer à notre petit blog de test, on pourrait ajouter un
profil à nos auteurs. En effet, chaque profil n’appartient qu’à un seul auteur et il
ne peut pas avoir plusieurs profils, ce serait bizarre non ? On va alors ajouter un
nouveau modèle Profile avec le contenu suivant :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Profile extends Model

public function author(): BelongsTo

return $this->belongsTo(Author::class);

// suite du model

Pour finir l’intégration de ce nouveau modèle, nous allons ajouter la mention


concernant le profil dans le modèle de notre auteur. On modifie donc notre
modèle Author avec cette nouvelle relation en plus du reste :

class Author extends Model

{
// code des précédentes relations

public function profile()

return $this->hasOne(Profile::class);

Bon, on y est presque pour le tour des relations ! Si vous suivez toujours, il nous
manque une petite dernière que nous allons illustrer facilement. Pour introduire
la relation belongsToMany dans notre super blog, on pourrait ajouter des
catégories pour nos articles. Vous avez maintenant l’habitude, on crée donc le
modèle Category :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Category extends Model

public function articles(): BelongsToMany

return $this->belongsToMany(Article::class);

La fonction articles() retourne une relation de type BelongsToMany, elle permet


de définir une relation de » plusieurs à plusieurs » entre les articles et les
catégories. Il nous faut maintenant modifier notre modèle Articles pour terminer
le travail. Pour cela, on va donc ajouter la relation suivante dans le modèle
Articles :

class Article extends Model

// précédentes relations
public function categories(): BelongsToMany

return $this->belongsToMany(Category::class);

// suite du model

MIDDLEWARE

Un Middleware est une mini-application, une étape intermédiaire qui va


envelopper les actions gérées par le controller. Elle est une sorte de sous-couche
se plaçant entre la requête (request) et la réponse (response) entre la vue et le
controller.

Pour schématiser cela donnerait quelque chose comme ça :

Il sert à introduire une logique, une condition pour exécuter telle ou telle
méthode présente dans le controller.

Laravel est installé avec quelques middlewares déjà présents, notamment :


• un système d’authentification afin de vous permettre de définir aisément si
une méthode doit être exécuter si la personne est authentifiée ou non sur notre
site web.
• un système de mode de maintenance
• une vérification des tokens CSRF pour les envois de formulaire

Ces Middlewares se situent dans app/Http/Middleware

Pour créer un nouveau middleware

php artisan make :middleware NomMiddleWare

Mettre en place le système dans laravel :

- Dans le controller au niveau de la méthode __construct

$this->middleware('auth');

- Au niveau des routes

Route::get('/', ([UtilisateursController::class, ‘liste’])->middleware('App\Http\Middleware\Auth');

- Au niveau de l’ensemble de mes applications

Il faut se rendre dans mon fichier Kernel.php se trouvant dans


app/Http/Kernel.php et ajouter le namespace dumiddleware dans le tableau
adéquat
SYSTEME D’AUTHENTIFICATION
Laravel ui
Laravel UI est un package fourni par Laravel qui fournit une interface utilisateur
prête à l'emploi pour l'authentification. Laravel UI utilise Bootstrap pour le style de
base, et offre une série de commandes pour générer les vues, les contrôleurs et
les routes nécessaires à l'authentification.

Pour commencer à utiliser Laravel UI, vous devez d'abord installer le package via
composer.
composer require laravel/ui

Une fois que vous avez installé Laravel UI, vous pouvez utiliser la commande ui
pour générer l'interface d'authentification. La commande suivante générera les
vues nécessaires à l'authentification, ainsi que les routes et les contrôleurs
correspondants :
php artisan ui bootstrap –-auth

php artisan ui bootstrap --auth


php artisan ui vue --auth
php artisan ui react --auth

Cette commande créera plusieurs fichiers dans votre application :

 Des vues pour la connexion, l'inscription, la réinitialisation du mot de passe


et la vérification de l'e-mail dans le dossier resources/views/auth.

 Un contrôleur HomeController dans app/Http/Controllers, qui est le


contrôleur par défaut après la connexion d'un utilisateur.

 Des routes pour l'authentification dans votre fichier de routes web


(routes/web.php).

Le système d'authentification généré par Laravel UI utilise les sessions pour


maintenir l'état de l'utilisateur. Cela signifie que lorsque l'utilisateur se connecte,
un cookie de session est créé et stocké dans le navigateur de l'utilisateur. À
chaque requête ultérieure, le cookie de session est envoyé au serveur, permettant
à Laravel de savoir qui est l'utilisateur.

Pour permettre à un utilisateur de se connecter, vous aurez besoin d'un


formulaire de connexion. Laravel UI génère un formulaire de connexion pour
vous, que vous pouvez trouver dans resources/views/auth/login.blade.php.

Le formulaire utilise la méthode POST pour envoyer les données à l'URL spécifiée
par la route login. Il utilise également une directive Blade @csrf pour générer un
champ de jeton CSRF, qui est une mesure de sécurité pour prévenir les attaques
de type Cross-Site Request Forgery.

Une fois que l'utilisateur a rempli le formulaire et cliqué sur le bouton de


soumission, les données du formulaire sont envoyées au serveur, où elles sont
traitées par la méthode login du contrôleur d'authentification. Si les informations
d'identification sont correctes, l'utilisateur est connecté et redirigé vers la page
d'accueil.

On peut faire une nouvelle installation de Laravel intégrant directement le


système d’authentification avec la commande
laravel new blog --auth

Lorsque l’utilisateur est authentifié, il sera redirigé vers l’url /home.

On peut modifier cette redirection dans RouteServiceProvider


public const HOME = '/home';
Breeze
Jetstream

Exemple pratique utilisation de ui et middleware


pour gerer des roles
Cet exemple montre comment mettre en place un système de middleware pour
gérer les rôles. On vérifie si l’utilisateur est un administrateur ou un simple
utilisateur. Si c’est un utilisateur, il ne pourra pas accéder aux pages admin.

Middleware : Le Middleware fournit un mécanisme pour filtrer les requêtes


HTTPS entrants de votre application. Il existe déjà dans Laravel un middlware qui
valide si un utilisateur est authentifié.

Dans notre exemple nous allons faire une nouvelle installation de Laravel. Voici
donc les étapes de la mise en place d’un middleware personnalisé :

Etape 1 – Installer Laravel App


Etape 2 – Connecter la base (.env)
Etape 3 – Générer Laravel Authentication
Etape 4 – Mettre à jour la Migration User
Etape 5 – Créer le Middleware
Etape 6 – Protéger les routes admin à l’aide du Middleware
Etape 7 – Créer & mettre à jour les fichiers Blade
Etape 8 – Mettre à jour les méthodes dans Controller
Etape 9 – Multiple Middlewares dans un seul Route

Etape 1: Installer Laravel App

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

Aller dans le dossier d’installation

Cd laravel-admin

Etape 2 – Connecter la base (.env)

Ouvre le fichier .env et renseigner les information de votre base de données

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_admin
DB_USERNAME=root
DB_PASSWORD=

Etape 3 – Générer Laravel Authentification

composer require laravel/ui


pnp --auth
npm install
npm run dev
npm run build

php artisan ui bootstrap --auth


php artisan ui vue --auth
php artisan ui react --auth
Etape 4 – Mettre à jour la Migration User

<?php

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

return new class extends Migration


{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->boolean('is_admin')->nullable();
$table->rememberToken();
$table->timestamps();
});
}

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

Après l’ajout de la colonne, lancer la migration

php artisan migrate

Etape 5 – Créer le Middleware

Maintenant créons le middleware qui va gérer le rôle admin

Php artisan make:middleware IsAdmin

Vérifier que vous avez bien le fichier dans \app\Http\Middleware\IsAsdmin.php


Ouvre le fichier et faite la modification comme suit
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Auth;

class IsAdmin
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if(Auth::user() && Auth::user()->is_admin == 1){
return $next($request);
}
return redirect('home')->with('error', 'You have not admin access');
}
}

Maintenent, ouvre le fichier app\ http\Kernel.php, ajoutons le middleware admin


au niveau de
$middlewareAliases

'admin' => \App\Http\Middleware\IsAdmin::class,

protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'precognitive' =>
\Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,

'admin' => \App\Http\Middleware\IsAdmin::class,


];
}
Etape 6 – Protéger les routes admin à l’aide du Middleware

Créez des routes qu'un administrateur doit protéger. Si l'utilisateur n'est pas un
administrateur, il sera redirigé vers la page d'accueil. Sinon, il peut visiter cette
page. Désormais, si je souhaite attribuer des routes à cet administrateur
middleware, ces routes seront sécurisées et accessibles uniquement si
l'utilisateur autorisé est un administrateur. Sinon, vous serez redirigé vers la page
d'accueil.

<?php

use Illuminate\Support\Facades\Route;
use \App\Http\Controllers\HomeController;
use \App\Http\Controllers\CategorieController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

Route::get('/', function () {

return view('welcome');

});

Auth::routes();

Route::get('home', [HomeController::class, 'index'])->name('home');

Route::group(['middleware' => ['admin']], function () {

Route::get('admin-home', [HomeController::class, 'adminHome'])-


>name('admin.home');

});

Etape 7 – Créer & mettre à jour les fichiers Blade

Ajoutons un lien d’accès vers la page admin depuis la page qui s’ouvre après la
connexion
resources\views\home.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Tableau de bord</div>

<div class="card-body">
@if (session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif

Vous êtes connecté !

</div>
<div class="card-body">
<div class="panel-body">
Test admin template:
<a href="{{route('admin.home')}}"> Page administrateur </a>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection

Créons un templates pour la page admin

resources\views\admin-home.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Page administrateur</div>

<div class="card-body">
Bienvenue dans le tableau de bord Administrateur
</div>
</div>
</div>
</div>
</div>
@endsection

Etape 8 – Mettre à jour les méthodes dans Controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HomeController extends Controller


{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}

/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('home');
}

public function adminHome()


{
return view('admin-home');
}
}
Dans le fichier route, vous pouvez regrouper les routes des liens pour
l’administrateur

Route::group(['middleware' => ['admin']], function(){


Route::get('admin-home', [HomeController::class, 'adminHome'])-
>name('admin.home');
});

Exemple pratique utilisation de ui et middleware


pour gérer des roles

Dans ce tutoriel sur Laravel, nous allons apprendre à gérer des rôles basiques à
l’aide d’un middleware. Nous allons avoir le rôle des utilisateurs classiques,
lorsqu’ils s’inscrivent tout simple sur notre site Web sous Laravel et le rôle
administrateur qui a des droits plus étendus. Le but vous l’avez compris, avec
l’aide du middleware, c’est que nos utilisateurs classiques ne puissent pas
accéder aux routes de l’administrateur. Par contre, l’administrateur pourra bien
évidemment se balader sur l’ensemble des pages du site et exécuter toutes les
routes comme un utilisateur normal de notre espace membre.

Modification de la base de données via les migrations

On commence par créer une première migration dans Laravel qui va s’occuper
de stocker nos différents rôles pour les utilisateurs :

php artisan make:migration create_roles_table

<?php

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

return new class extends Migration


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

public function down(): void


{
Schema::dropIfExists('roles');
}
};
Maintenant que l’on a de quoi stocker nos rôles, nous ajouter un seed pour
remplir cette table avec des valeurs par défaut qui ne devraient pas beaucoup
évoluer. Par la suite, nous pourrions ajouter autant de rôles que nous voulons et
les gérer comme nous allons le voir plus bas. Vous pouvez créer ce seed avec la
commande suivante :

php artisan make:seed RolesSeeder

Nous allons mettre en place 4 rôles :

 Le rôle administrateur (admin) qui aura accès à toutes les pages de mon
application avec par exemple un futur panel d’administration que nous
verrons dans un autre tutoriel.
 Le rôle utilisateur classique (user) que l’on obtient juste après son
inscription et qui ne permet pas d’accéder à l’administration du site
(heureusement).
 Le rôle abonné (subscriber) quand dans le cas où une partie de mon site
est payante, je pourrais basculer un utilisateur du rôle user à subscriber.
 Le rôle de gestionnaire (manager)

<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class RolesTableSeeder extends Seeder


{
public function run(): void
{
// Insérer les rôles dans la table "roles"
DB::table('roles')->insert([
['name' => 'admin'],
['name' => 'user'],
['name' => 'subscriber'],
]);
}
}
Pour pouvoir lancer l’exécution de notre seed fraîchement crée il faut que la table
existe réellement dans la base de données. Attention la commande suivante va
réinitialiser votre base de données et donc la vider totalement ! Sur une
application en développement, vous pouvez donc faire un :
php artisan migrate:fresh

Puis lancez ensuite la commande qui va remplir notre table rôle :

php artisan db:seed --class=RolesSeeder

Si vous avez bien suivi, vous êtes sûrement en train de vous dire qu’il manque
quelque chose ? En effet, il faut qu’on lie cette nouvelle table roles à la table des
users ! Étant donné qu’on a déjà la table user par défaut dans Laravel, on ne va
pas la toucher et on va plutôt refaire une migration pour ajouter cette relation de
roles sur users. On va créer donc une nouvelle migration
add_role_id_to_users_table :

php artisan make:migration add_role_id_to_users_table

Le contenu de cette nouvelle table add_role_id_to_users_table est alors le


suivant :

<?php

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

return new class extends Migration


{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->foreignId('role_id')->default(2); // Le rôle par défaut est "user"
$table->foreign('role_id')->references('id')->on('roles');
});
}

public function down()


{
Schema::table('users', function (Blueprint $table) {
$table->dropForeign(['role_id']);
$table->dropColumn('role_id');
});
}
};

Cette migration ajoute la colonne « role_id » à la table « users » avec une clé
étrangère vers la table « roles ». De plus, le rôle par défaut d’un nouvel utilisateur
qui s’inscrit est 2 et donc simple user. Lancez la commande suivante pour mettre
à jour votre base de données avec cette nouvelle migration :

php artisan migrate

Ajout et modification de modèle pour les rôles

Ajoutons un nouveau modèle Role


php artisan make:model Role

Un rôle va servir pour plusieurs utilisateurs, il faut donc créer la bonne relation. On
va ajouter le contenu suivant dans notre nouveau model Role :
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Role extends Model


{
public function users()
{
return $this->hasMany(User::class);
}
}

Un utilisateur ne peut avoir qu’un seul rôle. Donc attention, il ne faut surtout pas
oublier d’ajouter cette partie dans notre model User. Si vous ne le faites pas, alors
notre middleware ne pourra pas récupérer et vérifier le rôle de l’utilisateur
courant qui est authentifié. Voici ce que vous devez ajouter dans le model User :
public function role()
{
return $this->belongsTo(Role::class, 'role_id');
}

Création d’un middleware pour gérer les rôles

On va donc créer un middleware CheckRole avec la commande suivante :


php artisan make:middleware CheckRole

On va ajouter le contenu suivant dans mon fichier


app/Http/Middleware/CheckRole.php qui vient d’être créé :
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class CheckRole
{
public function handle(Request $request, Closure $next, $role): Response
{
try {
$user = auth()->user();

if (!$user || !$user->role || $user->role->name !== $role) {


// Journalisation de la tentative d'accès non autorisé
\Log::warning("Tentative d'accès non autorisé à la route avec le
rôle : $role");

return response()->json(['message' => 'Accès non autorisé.'], 403);


}
} catch (\Exception $e) {
// En cas d'erreur, retournez une réponse 403 générique
return response()->json(['message' => 'Accès non autorisé.'], 403);
}

return $next($request);
}
}

Quelques explications sur ce code qui va nous permettre de vérifier les rôles pour
l’accès aux pages de notre application Laravel :

 Authentification de l’utilisateur : la fonction commence par récupérer


l’utilisateur actuellement authentifié en utilisant auth()->user(). Si
l’utilisateur n’est pas authentifié, il n’y a pas d’utilisateur connecté, et la
vérification s’arrête ici.

 Vérification du rôle : si un utilisateur est authentifié, la fonction vérifie


ensuite si cet utilisateur a un rôle attribué. La présence d’un rôle est
cruciale pour déterminer s’il est autorisé à accéder à la route spécifiée.
C’est pour cela que par défaut, on attribue le rôle basique user plus haut
dans le tutoriel.

 Comparaison des rôles : la fonction compare ensuite le nom du rôle de


l’utilisateur avec le rôle spécifié en tant qu’argument $role. Si le rôle de
l’utilisateur ne correspond pas au rôle requis, l’accès est refusé.

 Journalisation des tentatives d’accès non autorisées : en cas de tentative


d’accès non autorisé, la fonction enregistre un message de journalisation
en utilisant Log::warning. Cette journalisation peut être très utile pour
suivre les activités suspectes ou pour diagnostiquer les problèmes de
sécurité. Il est bien sur possible d’ajouter d’autres informations dans le
message et vous pouvez même faire votre propre journal de log
personnalisé juste pour cet usage.

 Réponse d’erreur 403 : si l’accès est refusé, la fonction retourne une


réponse JSON avec un message d’erreur indiquant que l’accès n’est pas
autorisé et un code de statut HTTP 403 Accès refusé. J’ai fait le plus simple
possible dans le cadre de ce tutoriel. Il est bien sur possible de modifier
comment l’erreur s’affiche avec par exemple une belle page dédiée ou de
renvoyer l’utilisateur vers une page de paiement s’il a tenté d’accéder à une
ressource payante.

 Gestion des exceptions : la fonction est enveloppée dans un bloc try-catch


classique, ce qui signifie qu’elle gère les exceptions qui pourraient survenir
lors de la vérification du rôle. En cas d’erreur inattendue, elle renvoie une
réponse générique 403 pour des raisons de sécurité.

Il ne reste plus qu’une dernière modification pour cette partie, ajouter ce


middleware CheckRole dans app/Http/Kernel.php avec le bloc suivant :
protected $routeMiddleware = [
'role' => \App\Http\Middleware\CheckRole::class,
];

Test du middleware avec les routes de Laravel

Encore une fois le but est de rester le plus simple possible. On va donc créer des
routes basiques dans le fichier routes/web.php :

// Routes pour les membres (utilisateurs et administrateurs)


Route::middleware(['auth'])->group(function () {
// Route accessible à tous les membres (utilisateurs et
administrateurs)
Route::get('/testuser', function () {
$role = auth()->user()->role->name;
return "Bonjour $role !";
})->name('testuser');

// Routes accessibles uniquement aux administrateurs


Route::middleware(['role:admin'])->group(function () {
Route::get('/testadmin', function () {
$role = auth()->user()->role->name;
return "Wow un $role !";
})->name('testadmin');
});
});
PROJET DE CREATION LIVRE LARAVEL

CREATION BLOG

https://kinsta.com/fr/blog/blog-laravel/

https://www.xarala.co/blog/comment-creer-un-blog-avec-laravel-php-et-mysql/

https://www.educative.io/answers/how-to-verify-an-authenticated-user-in-blade

https://www.akilischool.com/cours/laravel-crud-avec-upload-dimage

Vous aimerez peut-être aussi