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

Tutoriel pour apprendre à utiliser le framework Laravel 4


précédentsommairesuivant

XIII. Chapitre 13 : Les bases de données 1/3

Nous allons à présent aborder un aspect important avec la gestion des bases de données. Laravel 4 est bien équipé dans ce domaine, comme nous allons le voir. Vous pouvez accéder à des bases MySQL, SQLite, SQL server et PostgreSQL.

XIII-A. Configuration

La configuration est simple et se passe dans le fichier app/config/database.php. Vous précisez le type de base :

 
Sélectionnez
'default' => 'mysql',

Par défaut on a MySQL, mais vous pouvez aussi mettre SQLite, PgSQL ou SQLSrv. Ensuite vous précisez les paramètres. Je vais prendre le cas le plus classique avec MySQL :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
'mysql' => array(
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'laravel',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
),

J'ai défini une base nommée laravel pour les tests. Laravel 4 sait faire beaucoup de choses, mais pas créer des bases : vous devez donc les créer vous-même par exemple avec PHPMyAdmin.

XIII-A-1. Migration

Laravel possède un outil bien pratique pour gérer la structure d'une base de données : Migration. C'est un outil en ligne de commande qui fait partie des commandes d'Artisan que nous avons déjà précédemment vu. Nous allons l'utiliser pour créer une table dans notre base. La première chose à faire est de créer une migration. Qu'est-ce que c'est ? Tout simplement un peu de code qui va nous permettre d'intervenir sur la structure de la base, de faire des modifications et de pouvoir revenir en arrière si besoin. Voyons ce que nous permet de faire cet outil :

Image non disponible

Et plus précisément ses paramètres utilisables :

Image non disponible

Commençons par créer une migration :

Image non disponible

Bon apparemment tout s'est bien passé, mais où est-elle cette migration ? Regardez ici :

Image non disponible

Un fichier a été créé avec un nom composé d'un timestamp (horodateur) et du nom que nous avons donné à la migration. De cette façon il est peu probable de se retrouver avec un conflit de nommage en cas de travail en équipe. Voyons ce fichier :

 
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.
<?php
 
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateEssences extends Migration {
 
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
    }
 
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //
    }
 
}

On y trouve une classe CreateEssences qui hérite de la classe Migration. On trouve aussi deux méthodes publiques up et down. C'est à nous de créer le code de ces méthodes. Dans up nous devons mettre le code qui va créer une modification dans la structure de la base, et dans down le code qui va faire l'inverse.

XIII-A-2. Le Schema builder

Pour créer le code de migration nous allons être aidés par la classe Schema d'Illuminate. Cette classe permet de créer et de supprimer facilement des tables, des colonnes et des index. Voyons ça de plus près avec un exemple simple :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
public function up()
{
    Schema::create('essences', function($table) {
        $table->increments('id');
        $table->string('nom_vulgaire', 100);
        $table->string('nom_latin', 100);
        $table->text('description');
    });
}

La syntaxe est si simple qu'elle se passe presque de commentaires. La méthode create permet de créer une table. On transmet le nom de la table à une fonction anonyme qui permet de définir les colonnes. Vous pouvez trouver toutes les possibilités de types de colonnes dans la documentation. Notez que Eloquent a besoin que chaque table ait une clé primaire numérique nommée id pour bien fonctionner (ce n'est pas indispensable mais ça simplifie la syntaxe). Maintenant nous allons activer la migration pour créer notre table :

Image non disponible

On nous dit que la migration s'est bien effectuée. Allons voir ça. Nous trouvons deux tables dans notre base : essences et migrations. La première est celle que nous avons créée :

Image non disponible

Elle comporte exactement ce que nous avons prévu pour elle. La seconde sert à la gestion des migrations. Maintenant nous devons nous occuper de l'action inverse de notre migration, autrement dit la suppression de la table :

 
Sélectionnez
1.
2.
3.
4.
public function down()
{
    Schema::drop('essences');
}

Il ne reste plus qu'à commander le rollback (retour en arrière):

Image non disponible

Et vous pouvez vérifier que la table a bien été supprimée. Comme nous avons besoin de la table pour la suite, faites à nouveau une migration pour la recréer.

Vous pouvez ajouter 2 options (-table= et -create) dans votre migration pour obtenir une architecture de code plus complète :

Image non disponible

Vous obtenez ce code :

 
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.
<?php
 
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateEssencesTable extends Migration {
 
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('essences', function(Blueprint $table)
        {
            $table->increments('id');
            $table->timestamps();
        });
    }
 
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('essences');
    }
 
}

XIII-A-3. Des données d'exemple

Il existe aussi un moyen simple pour générer des données d'exemple. Créez un fichier app/database/seeds/EssenceTableSeeder.php avec ce code (nous verrons en détail la syntaxe pour la modification des données dans une table) :

 
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.
class EssenceTableSeeder extends Seeder {
 
    public function run()
    {
        DB::table('essences')->insert(
 
            array(
                array(
                    'nom_vulgaire' => 'Basilic exotique',
                    'nom_latin' => 'Ocimum basilicum ssp basilicum',
                    'description' => 'Cette huile essentielle est antibactérienne...'
                ),
 
                array(
                    'nom_vulgaire' => 'Bergamotier',
                    'nom_latin' => 'Citrus bergamia',
                    'description' => 'Cette huile essentielle est...'
                )
            )
 
        );
    }
 
}

Il faut aussi modifier le fichier app/database/seeds/DatabaseSeeder.php pour appeler votre classe :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
class DatabaseSeeder extends Seeder {
 
    public function run()
    {
        $this->call('EssenceTableSeeder');
    }
 
}

Lancez ensuite cette commande de migration :

Image non disponible

Allez voir dans votre base le résultat :

Image non disponible

On peut se poser une question : pourquoi ne pas faire cette opération dans la migration ? On pourrait effectivement le faire et ça fonctionnerait, mais il est bon de bien séparer les fonctionnalités. La migration a pour but d'intervenir au niveau de la structure de la base alors que les seeds se contentent d'en modifier le contenu. Vous pourrez me dire aussi que le contenu sera renseigné au fil du temps à partir d'autres interfaces (administration, formulaire…), mais il y a parfois des données qui doivent être renseignées à la création d'un site : une liste de villes, des codes postaux, un compte administrateur, des catégories… Toutes ces données initiales se trouveront ici à leur place.

XIII-A-4. Les modifications ultérieures

Et la suite ? Imaginez que vous voulez faire une modification dans une de vos tables, devez-vous faire un rollback, modifier le schéma, et faire une nouvelle migration ? Bon vous aboutirez bien sûr au résultat, mais si vous avez déjà entré des données vous n'allez pas apprécier de les perdre dans la manœuvre Image non disponible. Il est possible de faire une nouvelle migration en effectuant juste la modification nécessaire. Par exemple vous voulez rendre unique la ligne du nom latin :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
public function up()
{
    Schema::table('essences', function($table) {
        $table->unique('nom_latin', 'essences_nom_latin_unique');
    });
}

Sans oublier la manœuvre inverse :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
public function down()
{
    Schema::table('authors', function($table) {
        $table->dropUnique('essences_nom_latin_unique');
    });
}

XIII-A-5. Scénario de migrations

Comme le processus de migration n'est pas toujours bien perçu je vous propose un petit scénario pour passer en revue les commandes disponibles. Partons d'une installation vierge de Laravel.

XIII-A-5-a. Installation

La première commande disponible est migrate:install qui est destinée à créer la table des migrations dans la base :

Image non disponible
Image non disponible

Cette opération n'est pas indispensable parce que si cette table n'existe pas elle sera créée lors de la première migration effectuée.

XIII-A-5-b. Première migration

Créons maintenant notre première migration. Imaginons que nous voulons une table d'auteurs. On commence par créer la migration en lui donnant un nom explicite, et tant qu'à faire on utilise les options pour générer le maximum de code :

Image non disponible

Le fichier est créé :

Image non disponible

Avec ce code :

 
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.
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateAuteursTable extends Migration {
 
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('auteurs', function(Blueprint $table)
        {
            $table->increments('id');
            $table->timestamps();
        });
    }
 
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('auteurs');
    }
 
}

Ajoutons un champ, par exemple le nom de l'auteur :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
Schema::create('auteurs', function(Blueprint $table)
{
    $table->increments('id');
    $table->timestamps();
    $table->string('nom');
});

Et maintenant activons cette migration :

Image non disponible

La table « auteurs » est bien créée avec les champs attendus :

Image non disponible
XIII-A-5-c. Ajout d'un champ

Maintenant on se rend compte qu'on a oublié le champ « email », comment l'ajouter ? On pourrait faire un rollback pour supprimer la table, faire la modification et relancer la migration. Mais il est plus simple de créer une nouvelle migration pour cet ajout :

Image non disponible

Rappelez-vous que vous donnez le nom que vous voulez à la migration, faites en sorte que ce soit explicite pour vous. On a donc un nouveau fichier :

Image non disponible

Avec ce code :

 
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.
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class AddEmailToAuteurs extends Migration {
 
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
    }
 
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //
    }
 
}

Ajoutons le code pour notre email :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
public function up()
{
    Schema::table('auteurs', function($table) {
            $table->string('email', 64);
    });
}
 
    ....
 
public function down()
{
    Schema::table('auteurs', function($table) {
            $table->dropColumn('email');
    });
}

Et lançons cette migration :

Image non disponible
Image non disponible
XIII-A-5-d. Retour en arrière

Finalement on se rend compte qu'on n'a pas besoin de l'email, alors on supprime la dernière migration :

Image non disponible
Image non disponible

On a bien la suppression de l'email dans la base.

XIII-A-5-e. Ajout d'une table

Maintenant on veut ajouter une table des livres :

Image non disponible
Image non disponible

Avec encore le code de base :

 
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.
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateLivresTable extends Migration {
 
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('livres', function(Blueprint $table)
        {
            $table->increments('id');
            $table->timestamps();
        });
    }
 
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('livres');
    }
 
}

Ajoutons un champ :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
Schema::create('livres', function(Blueprint $table)
{
    $table->increments('id');
    $table->timestamps();
    $table->string('titre');
});

Et lançons la migration :

Image non disponible

Remarquez que deux migrations ont eu lieu, et c'est logique. Puisqu'on avait fait un rollback pour l'email, cette migration existe toujours et n'est pas effectuée, donc la commande migrate l'active. Si on avait voulu éviter cela il aurait suffit de supprimer le fichier correspondant qui n'avait plus de raison d'être si cet email était vraiment à supprimer. On trouve bien la table des livres avec les champs attendus :

Image non disponible
XIII-A-5-f. Épurer une migration

Revenons sur le cas de l'email . On se rend compte que finalement on n'en voulait pas, comment le supprimer maintenant ? Faisons deux rollbacks :

Image non disponible

Maintenant supprimons le fichier de la migration de l'email :

Image non disponible

Et faisons une migration :

Image non disponible

Nous obtenons bien ce que nous voulions : suppression de l'email et création de la table des livres.

XIII-A-5-g. Rafraichissement des migrations

Il est parfois utile de relancer toutes les migrations (par exemple si on a effectué quelques modifications dans les fichiers des migrations) Pour faire cela il y a la commande refresh :

Image non disponible

On a les rollbacks dans l'ordre et les migrations qui se relancent, dans l'ordre aussi.

XIII-A-5-h. Suppression de toutes les migrations

Enfin on peut aussi vouloir supprimer toutes les migrations effectuées, on le fait avec la commande reset :

Image non disponible

Cette fois on n'a que les rollbacks.

***

Nous avons donc vu comment gérer la structure d'une base de données, nous verrons dans une prochaine étape comment manipuler des données.


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.