Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Laravel
  3. Eloquent ORM
Extrait - Laravel Un framework efficace pour développer vos applications PHP (2e édition)
Extraits du livre
Laravel Un framework efficace pour développer vos applications PHP (2e édition) Revenir à la page d'achat du livre

Eloquent ORM

Object Relational Mapping

1. À propos des modèles

Dans un contexte MVC (modèle-vue-contrôleur), et en particulier en programmation orientée objet, un modèle représente les données et la logique liée à ces données.

Voici quelques exemples de modèles pour un site de type e-commerce :

  • Produit

  • Commande

  • Utilisateur

Avec Laravel, un modèle est représenté par une classe avec des propriétés et des méthodes. Il est généralement lié à une table dans la base de données. L’ORM (Object-Relational Mapping) Eloquent permet de créer une correspondance entre les classes PHP et la base de données.

Ainsi, grâce à Eloquent, on pourra créer une classe Product pour représenter un produit, cette classe sera ainsi associée à une table products. Eloquent pourra accéder aux colonnes de la table au travers des propriétés de la classe et bénéficier de méthodes pour charger un produit, enregistrer un produit, lister tous les produits ou encore mettre à jour un produit.

2. Manipuler des objets

Eloquent permet donc de manipuler des objets de manière simple et intuitive en créant une abstraction au-dessus de la base de données. Ainsi, manipuler des données SQL se fait naturellement en utilisant des objets PHP....

Construire des modèles

1. Utiliser Artisan

a. Initialisation d’un modèle

La méthode la plus simple pour créer un modèle est d’utiliser Artisan. Pour rappel, Artisan est l’outil mis à disposition par Laravel qui permet de lancer des commandes depuis un terminal. Pour créer une classe permettant de manipuler les articles du blog de jardinage http://mon-jardin.com, il faudra donc indiquer à Artisan de construire un modèle Article, chaque article étant un nouveau conseil sur le jardinage dans cet exemple. Utilisez pour cela la commande ci-dessous depuis le terminal.

Commande Artisan pour créer un modèle Article

sail artisan make:model Article  

Par convention, les modèles commencent tous par une majuscule, étant donné qu’ils sont représentés par des classes et que les classes commencent toutes par une majuscule. Il faudra donc privilégier les noms en notation CamelCase, comme par exemple ArticleJardin, plutôt que article_jardin. De plus, le nom de la classe sera toujours au singulier, ce qui signifie qu’un article sera représenté par Article plutôt que par Articles.

Le modèle créé est ajouté dans le dossier app/Models de l’application Laravel. Il s’agit pour l’instant d’une classe sans méthodes ni propriétés propres qui hérite de la classe Model.

Structure d’une classe Article, classe App\Models\Article

<?php 
 
namespace App; 
 
use Illuminate\Database\Eloquent\Model; 
 
class Article extends Model 
{ 
    // 
}  

b. Modèles et migrations

Un modèle sans table associée est rarement suffisant. En effet, un modèle est fait pour enregistrer dans une base de données. Les articles du blog mon-jardin.com doivent ainsi être enregistrés pour pouvoir être réaffichés plus tard. Ils peuvent potentiellement être modifiés ou supprimés. Créer une migration permet de décrire la table associée à un modèle.

Il est possible de créer une migration en même temps que la création du modèle. Pour cela, ajoutez le paramètre --migration dans la commande...

Utiliser des modèles

1. Créer et enregistrer une instance de modèle

a. Instancier un modèle

Une fois la classe de modèle générée et la table construite, créer une nouvelle instance d’un modèle se fait à l’aide du mot-clé new sur la classe, comme pour créer n’importe quel autre objet en PHP.

Création de trois instances d’utilisateurs

$user1 = new User; 
$user1->name = 'Colyne'; 
 
$user2 = new User; 
$user2->name = 'Arthur'; 
 
$user3 = new $user; 
$user3->name = 'Brian';  

Les instances d’un modèle peuvent être créées n’importe où dans le code : dans une méthode d’un contrôleur ou directement dans la fonction de rappel d’une route.

b. Enregistrement d’un modèle

Enregistrer un modèle se fait grâce à la fonction save disponible sur toutes les instances de modèles. Le mot-clé new crée une instance en mémoire pour la manipuler en PHP, tandis que la méthode save enregistre cette instance dans la base de données.

Enregistrement de trois instances d’utilisateurs

// Initialisation, définitions de propriétés 
$user1 = new User; 
$user1->name = 'Colyne'; 
 
$user2 = new User; 
$user2->name = 'Arthur'; 
 
$user3 = new $user; 
$user3->name = 'Brian'; 
 
// Enregistrement dans la base de données 
$user1->save(); 
$user2->save(); 
$user3->save();  

Lorsqu’un modèle est enregistré, cela signifie qu’il est enregistré dans une base de données. Il pourra donc y être retrouvé par la suite.

c. Créer et enregistrer un modèle en une ligne

Il est possible de créer et de sauvegarder un modèle directement dans la base de données en une seule instruction grâce à la méthode statique create disponible sur tous les modèles.

Création d’un utilisateur

User::create([ 
    'name' => 'Brian', 
    'email' => 'brian@example.com' 
]);  

Cette méthode retourne le modèle...

Les relations

Dans la conception et l’architecture d’une base de données SQL, l’un des points les plus importants à prendre en compte est la notion de relations. Par exemple, voici quelques relations pour une application de base de données documentaire permettant la création de documents et l’ajout de commentaires :

  • Un utilisateur possède des documents.

  • Un document peut avoir différents commentaires.

  • Un commentaire appartient à un utilisateur.

  • Etc.

Les verbes ci-dessus décrivent les relations. Dans la base de données, les relations sont généralement créées à l’aide de clés étrangères dans les tables. Au-delà de simplement définir les règles au niveau du schéma, Eloquent permet de faciliter l’accès en lecture et écriture aux relations entre les objets dans le code PHP.

Il existe trois grands types de relations entre des entités : « 1..1  », « 1..n  » et « n..n  ».

1. Relations 1..1

La relation 1..1 (one-to-one) correspond comme son nom anglais l’indique à une relation unique entre deux entités. Une entité est généralement représentée par un modèle.

Par exemple, si deux entités Company (société) et Address (adresse) existent, on peut déclarer qu’une société possède une et une seule adresse et qu’une adresse appartient à une et une seule société. Il y a donc une relation de un à un.

Dans la suite de cette section sur les relations 1..1, cet exemple de société liée à une adresse sera gardé et déroulé entièrement, de la création des modèles à l’utilisation et la sauvegarde d’instances.

a. Création des modèles

Pour commencer, cette contrainte doit être codée dans la base de données puis indiquée dans les modèles. Créez d’abord les modèles et leurs migrations associées avec Artisan.

Création des modèles

php artisan make:model Company --migration 
 
php artisan make:model Address -migration  

b. Structure des tables

Ensuite, il faut...

Mutation, accesseurs et transformation

1. Accesseurs

Les accesseurs permettent de définir des attributs personnalisés sur les modèles. Ce mécanisme peut être utilisé lorsqu’on souhaite modifier la façon dont une colonne est affichée en particulier, ou lorsqu’on souhaite créer un attribut personnalisé qui n’existe pas dans la table de la base de données.

Par exemple, dans l’espace administration d’un site, on peut vouloir afficher le nom de famille des utilisateurs en majuscules. Si la base de données contient une liste d’utilisateurs dont le nom n’est pas toujours en majuscule, il sera possible de forcer la transformation du nom en majuscule dès qu’on y accède depuis le code PHP. Autrement dit, un accesseur permet de traiter différemment le stockage et l’affichage.

Pour définir un accesseur, ajoutez une méthode sur le modèle du nom de l’attribut à renvoyer et qui renverra une instance de l’objet Illuminate\Database\Eloquent\Casts\Attribute à instancier en lui passant un paramètre get à son constructeur. Pour créer un accesseur sur un attribut author_name, il faut créer une méthode authorName. L’accesseur peut faire référence soit à une colonne existante (par exemple pour donner une valeur par défaut si la propriété est vide), soit à un attribut créé de toute pièce.

Dans l’exemple ci-dessous, le modèle Book possède...

Surveiller les performances

Selon les besoins de l’application, il arrive que l’on ait besoin de charger une grande quantité de modèles ainsi que leurs relations et de l’afficher dans une vue. Lors de la phase de développement, il est possible de surveiller la façon dont Eloquent récupère les données dans la base de données (nombre de requêtes SQL, temps d’exécution, nombre de modèles instanciés) grâce au package barryvdh/laravel-debugbar. Une fois installé, une barre d’information s’affiche sur chaque page de notre application avec de nombreuses informations concernant la performance sur la page générée.

Installation du package barryvdh/laravel-debugbar

sail composer require barryvdh/laravel-debugbar --dev  

Pour illustrer un problème de performance, reprenons les modèles User et Article du début du chapitre. Ils sont liés par une relation 1..n, chaque utilisateur pouvant être lié à un ou plusieurs articles. Dans une vue, nous allons afficher la liste des utilisateurs avec le nombre d’articles pour chaque utilisateur et étudier comment optimiser le chargement des données par Eloquent.

Création du contrôleur associé au modèle User

sail artisan make:controller UserController  

Contenu de la classe App\Http\Controllers\UserController

<?php 
 
namespace App\Http\Controllers; 
 
use App\Models\User; 
use Illuminate\View\View; 
 
class UserController extends Controller 
{ 
 
    public function index(): View 
    { 
 
        $users = User::all(); 
        return view('users.index', compact('users')); 
 
    } 
 
}  

Nous allons associer une route /users à la méthode index de notre contrôleur afin de pouvoir charger la vue dans notre navigateur.

Ajout de la route, fichier routes/web.php

Route::get('/users', [UserController::class, 'index']);  

Vue listant les utilisateurs, fichier resources/views/users/index.blade.php

<body > 
 
    <h1>Liste...