IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Tutoriel pour apprendre à utiliser le framework Laravel 4


précédentsommairesuivant

XV. Chapitre 15 : Les bases de données 3/3

Maintenant que nous savons mettre en place la structure d'une base de données et intervenir sur les enregistrements que nous reste-t-il à voir ? Et bien Laravel nous propose un ORM vraiment efficace nommé Eloquent. Qu'est-ce qu' un ORM ? C'est un « Object Relational Mapper ». Mapper parce qu'on va « mapper » des objets PHP sur les tables et les colonnes d'une base. Relational parce qu'on va aussi pouvoir gérer les relations de notre base. Mais tout cela va devenir plus clair avec des exemples. Vous n'avez pas besoin d'un ORM pour gérer une base, mais vous le ferez avec beaucoup plus de facilité avec lui. Image non disponible

Je pars du principe que vous avez une base nommée laravel telle que décrite lors du chapitre précédent avec deux tables : auteurs et livres. Vous avez aussi correctement configuré le fichier app/config/database.php pour accéder à la base.

XV-A. Créer un modèle avec Eloquent

Voyons comment créer un modèle avec Eloquent. Par exemple pour notre table auteurs. Créez un fichier avec ce code et enregistrez-le dans app/models/Auteur.php :

 
Sélectionnez
<?php
class Auteur extends Eloquent {}

Et voilà vous avez créé un modèle et vous pouvez maintenant l'utiliser Image non disponible. Bon il a quand même fallu prendre quelques précautions : j'ai nommé la classe Auteur, autrement dit le nom de la table avec le « s » en moins. En effet la table peut contenir plusieurs auteurs mais la classe s'adresse à un auteur à chaque fois. D'autre part il est impératif que la table contienne une clé nommée « primaire id », ce qui est notre cas.

XV-A-1. Extraire des données

Il ne nous reste plus qu'à utiliser notre nouvelle classe. Dans une route entrez ce code :

 
Sélectionnez
$auteur = Auteur::find(1);
var_dump($auteur);

On demande l'enregistrement avec l'index 1. Voyons ce que nous avons en retour :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
object(Auteur)[118]
protected 'connection' => null
protected 'table' => null
protected 'primaryKey' => string 'id' (length=2)
protected 'perPage' => int 15
public 'incrementing' => boolean true
public 'timestamps' => boolean true
protected 'attributes' =>
array (size=4)
'id' => int 1
'nom' => string 'Flaubert' (length=8)
'prenom' => string 'Gustave' (length=7)
'naissance' => string '1821-12-12' (length=10)
protected 'original' =>
array (size=4)
'id' => int 1
'nom' => string 'Flaubert' (length=8)
'prenom' => string 'Gustave' (length=7)
'naissance' => string '1821-12-12' (length=10)
protected 'relations' =>
array (size=0)
empty
protected 'hidden' =>
array (size=0)
empty
protected 'fillable' =>
array (size=0)
empty
protected 'guarded' =>
array (size=0)
empty
protected 'dates' =>
array (size=0)
empty
public 'exists' => boolean true

Maintenant nous comprenons mieux la notion de mappage : Nous obtenons un objet que nous pouvons exploiter pour extraire des informations. Ce qui est bien pratique aussi, c'est que tout ce que nous avons vu au chapitre précédent concernant la gestion des enregistrements reste valable. Ainsi nous pouvons écrire :

 
Sélectionnez
$auteur = Auteur::where('nom', '=', 'Saulers')->get();
var_dump($auteur[0]->nom);

Ce qui donne :

 
Sélectionnez
string 'Saulers' (length=7)

Eloquent nous renvoie une collection qui implémente l'interface IteratorAggregate. Nous pouvons donc agir comme si nous avions un tableau en retour. En effet notre requête est susceptible de renvoyer plusieurs lignes, contrairement au cas précédent où on appelait juste une ligne en précisant son index. Il devient alors facile de traiter les lignes lorsqu'elles nous arrivent sous cette forme :

 
Sélectionnez
$auteurs = Auteur::where('nom', '>', 'q')->get();
foreach ($auteurs as $auteur) var_dump($auteur->nom);

Ce qui donne :

 
Sélectionnez
string 'Raspail' (length=7)
string 'Sibran' (length=6)
string 'Saulers' (length=7)

XV-A-2. Insérer des données

Nous allons voir qu'il est aussi très facile d'insérer de nouvelles données. Mais auparavant je dois vous donner encore une petite indication. Par défaut Eloquent gère deux colonnes dans chaque table de type DateTime nommées respectivement updated_at et created_at. Ces colonnes sont automatiquement mises à jour à chaque création ou modification. Mais vous n'êtes pas obligé de les avoir. Si ces informations ne vous intéressent pas il suffit de compléter le modèle ainsi :

 
Sélectionnez
1.
2.
3.
4.
5.
<?php
class Auteur extends Eloquent
{
    public $timestamps = false;
}

C'est ce que nous allons faire dans notre cas parce que nous n'avons pas prévu ces colonnes dans nos tables. Sachez juste que cette possibilité existe et nous l'utiliserons dans un article ultérieur sur la création d'un blog. Maintenant voilà le code pour faire une insertion :

 
Sélectionnez
1.
2.
3.
4.
5.
$auteur = new Auteur;
$auteur->nom = 'Frain';
$auteur->prenom = 'Irène';
$auteur->naissance = '1950-06-22';
$auteur->save();

On vérifie dans la base :

Image non disponible

Apparemment tout se passe bien. Vous pouvez aussi passer un tableau au constructeur :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
$auteur = new Auteur(array(
    'nom' => 'Frain',
    'prenom' => 'Irène',
    'naissance' => '1950-06-22'
));
$auteur->save();

XV-A-3. Modifier et supprimer des données

Pour modifier une donnée existante la syntaxe est tout aussi simple, voici un exemple :

 
Sélectionnez
$auteur = Auteur::find(8);
$auteur->prenom = 'Claire';
$auteur->save();
Image non disponible

Pour supprimer des données c'est tout aussi simple :

 
Sélectionnez
$auteur = Auteur::find(8);
$auteur->delete();

XV-A-4. Les relations

Par définition dans une base de données relationnelle nous avons des… relations. Celles-ci peuvent être explicites dans la base ou implicites (comme c'est le cas dans notre exemple où on a juste introduit une ligne dans la table des livres pour préciser l'id de l'auteur mais sans demander à MySQL de vérifier l'intégrité de cette relation. On aurait pu le faire en précisant que nous utilisons le moteur InnoDB et en déclarant cette ligne comme clé étrangère).

Eloquent a une façon très élégante de gérer les relations. Nous allons prendre comme exemple celle qui existe entre nos deux tables. Mais auparavant il nous faut créer aussi un modèle pour la table des livres (app/models/Livre.php) :

 
Sélectionnez
1.
2.
3.
4.
class Livre extends Eloquent
{
    public $timestamps = false;
}

Il existe trois sortes de relations : « un vers un », « un vers plusieurs » et « plusieurs vers plusieurs ». Notre cas est le plus classique avec une relation « un vers plusieurs », en effet un auteur peut écrire plusieurs livres et on admet qu'un livre n'est écrit que par un auteur (bon on oublie les coauteurs Image non disponible).

Pour qu'Eloquent reconnaisse automatiquement la clé étrangère dans une table il faut qu'elle réponde à une certaine syntaxe : le nom de la table suivi d'un soulignement puis de « id ». Manque de chance j'ai fait juste l'inverse dans la table des livres. On va corriger ça :

Image non disponible

Cette norme n'est pas une contrainte absolue parce que d'une part on peut préciser le nom de la clé étrangère comme paramètre des méthodes relationnelles, d'autre part elle n'est pas toujours respectée par Eloquent (par exemple pour belongsTo c'est le nom de la méthode qui sert de référence). Pour avoir une vue d'ensemble du sujet, référezvous au chapitre 33Chapitre 33 : Les relations avec Eloquent 1/2.

Maintenant nous pouvons utiliser toute la puissance et l'élégance d'Eloquent. Nous modifions la classe Auteur pour déclarer la relation :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
class Auteur extends Eloquent
{
    public $timestamps = false;
    public function livres()
    {
        return $this->hasMany('Livre');
    }
}

Et maintenant ça devient facile :

 
Sélectionnez
$livres = Auteur::find(2)->livres;
foreach($livres as $livre) var_dump($livre->titre);

Résultat :

 
Sélectionnez
string 'Secouons le cocotier' (length=20)
string 'Les Royaumes de Borée' (length=22)

On peut mettre en œuvre toutes les possibilités de manipulation de données. Par exemple si on ne veut que le premier livre :

 
Sélectionnez
$livre = Auteur::find(2)->livres()->first();
var_dump($livre->titre);

Résultat :

 
Sélectionnez
string 'Secouons le cocotier' (length=20)

XV-A-5. Inverse d'une relation

Considérons à nouveau notre relation en la regardant dans l'autre sens. Nous avons dit qu'un auteur peut écrire plusieurs livres. Nous avons traduit cela dans la classe Auteur par ce code :

 
Sélectionnez
1.
2.
3.
4.
public function livres()
{
    return $this->hasMany('Livre');
}

On pourrait aussi dire qu'un livre appartient à un auteur. Cette fois au lieu de renseigner la relation dans la classe Auteur on le fait dans la classe Livre :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
<?php
class Livre extends Eloquent
{
    public $timestamps = false;
    public function auteur()
    {
        return $this->belongsTo('Auteur');
    }
}

Testons cela :

 
Sélectionnez
$auteur = Livre::find(1)->auteur;
var_dump($auteur->nom);

Résultat :

 
Sélectionnez
string 'Raspail' (length=7)

XV-A-6. Chargement dynamique

Avec la relation précédente, considérez ce code :

 
Sélectionnez
foreach(Livre::all() as $livre)
echo '"'.$livre->titre.'" a été écrit par '.$livre->auteur->nom.'<br>';

Et son résultat :

 
Sélectionnez
1.
2.
3.
4.
"Secouons le cocotier" a été écrit par Raspail
"Pêcheurs de Lune" a été écrit par Avril
"Les Royaumes de Borée" a été écrit par Raspail
"Le Salon des artistes" a été écrit par July

Le résultat correspond à notre attente mais… nous ne sommes pas très efficaces parce que nous multiplions les requêtes. Il y en a une pour récupérer tous les livres, et ensuite une pour chaque livre afin de trouver l'auteur. Imaginez que nous ayons des milliers de livres ! Heureusement il existe une solution :

 
Sélectionnez
foreach(Livre::with('auteur')->get() as $livre)
echo '"'.$livre->titre.'" a été écrit par '.$livre->auteur->nom.'<br>';

Cette fois on a une seule requête dans la boucle, qui prend la forme :

 
Sélectionnez
SELECT * FROM auteurs WHERE id IN (2,3,7);

Il y aurait encore beaucoup à dire sur Eloquent. Je vous renvoie encore une fois à la documentation. Vous pouvez également consulter le chapitre 33Chapitre 33 : Les relations avec Eloquent 1/2 qui est consacré à ce sujet.


précédentsommairesuivant

Copyright © 2017 Laravel. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.