Tutoriel de site dynamique - Classes d'abstraction


précédentsommairesuivant

II. La base de données

II-A. Introduction

Il existe de nombreuses classes d'abstraction de bases de données. Parmi les plus connues, on compte PEAR::DB et PDO ; de plus, chaque collection de scripts (comme phpBB) a développé sa propre classe... Je vais vous proposer d'utiliser PDO (PHP Data Objects).

PDO est disponible à partir de PHP 5.0 ou 5.1 suivant votre système d'exploitation.

Pour charger l'extension, il faut activer deux lignes de votre fichier php.ini : "extension=php_pdo" ainsi que "extension=php_pdo_mysql" (suivant votre système de gestion de base de données, ici MySQL).

II-B. Principe

Commençons par déterminer la problématique.

Schéma classique d'interrogation d'une base de données avec MySQL :
Sélectionnez
<?php

$id = 10;

mysql_connect("server", "login", "password")
    or die(basename(__FILE__)."<br />".__LINE__."<br />".mysql_error());
mysql_select_db("database")
    or die(basename(__FILE__)."<br />".__LINE__."<br />".mysql_error());

$sql = "SELECT `field` FROM `table` WHERE `id` < ".$id;
$result = mysql_query($sql)
    or die(basename(__FILE__)."<br />".__LINE__."<br />".mysql_error());

while($row = mysql_fetch_assoc($result)
{
    echo "field: ".$row["field"]."<br />";
}

mysql_close();

?>


Le problème est le suivant : si je souhaite donner ce script à quelqu'un ou bien si je change de serveur de bases de données, je serai contraint de réécrire tout le code qui concerne la base de données (puisque les fonctions MySQL ne seront plus disponibles).
La solution est d'utiliser ce que l'on appelle un wrapper, c'est-à-dire des fonctions ou une classe qui me permettent de faire la même chose sans appeler aucune fonction spécifique à un système en particulier (ici : MySQL).

Schéma classique d'interrogation d'une base de données avec PDO :
Sélectionnez
<?php

$id = 10;
try
{
    $db = new PDO("mysql:host=server;dbname=database", "login", "password");
    
    $sql = 'SELECT `field` FROM `table` WHERE `id` < :id';
    $statement = $db->prepare($sql);
    $statement->execute(array(":id" => $id));
    
    if($rows = $statement->fetchAll())
    {
        foreach($rows as $row)
        {
            echo "field: ".$row["field"]."<br />";
        }
    }
    
    $db = NULL;
}
catch (PDOException $exception)
{
    die("Erreur : " . $exception->getMessage() . "<br/>");
}

?>

Avec cette technique, un changement de SGBD se fait simplement en modifiant l'instanciation de l'objet de la classe PDO !

II-C. Procédure

Quelle est la procédure pour réécrire un script ?
Il faut trouver tous les appels à des fonctions spécifiques au SGBD utilisé et les remplacer par leur équivalent en utilisant la classe d'abstraction.

Trouver dans le fichier : index.php
Sélectionnez
connexion_DB("developpez");
Remplacer par :
Sélectionnez
define("BDD_CONNECTION", "mysql:host=localhost;dbname=BASE_TEST");

set_exception_handler("exception_handler");
$db = new PDO(BDD_CONNECTION, "root", "");


Nous venons d'instancier l'objet de base de données. C'est cet objet $db que nous utiliserons tout au long du script.
Nous avons aussi assigné la gestion des erreurs à une fonction. Cela nous permet d'éviter d'écrire les blocs try-catch comme ci-dessus. Chacun sa méthode de faire : ici, j'ai opté pour le plus simple. Dans une application réelle, il est conseillé d'attraper l'exception et de la gérer correctement. D'une manière ou d'une autre, il est fortement conseillé de gérer l'erreur (au moyen du gestionnaire ou bien au moyen de try-catch) car, en cas d'erreur non gérée, PHP afficherait toutes les informations nécessaires au débogage (y compris le mot de passe de l'utilisateur de la base de données) !
La fonction de gestion d'erreurs est la suivante :

Ajouter dans le fichier : mes-fonctions.php
Sélectionnez
function exception_handler($exception)
{
    $message  = "Wrong query : " . $exception->getMessage() . "<br>\n";
    $message .= "Please, send this message to the webmaster";
    die($message);
}


Nous n'aurons plus besoin de la fonction "connexion_DB", nous pouvons donc la supprimer. Il en va de même pour la fonction "deconnexion_DB".
Voici maintenant comment procéder à l'exécution d'une requête :

Trouver dans le fichier : mes-fonctions.php
Sélectionnez
$strSQL = "SELECT * FROM PAGES WHERE Id_page = ".$_ENV["id_page"];
$resultat = requete_SQL($strSQL);
$tabl_result = mysql_fetch_array($resultat);
Remplacer par :
Sélectionnez
global $db;

$sql = "SELECT * FROM PAGES WHERE Id_page = :id_page";
$statement = $db->prepare($sql);
$statement->execute(array(":id_page"   => $_ENV["id_page"]));
$tabl_result = $statement->fetch();


Le processus est très similaire à ce que nous connaissons déjà. Il s'agit de préparer la requête, de l'exécuter et de récupérer les résultats. L'étape de préparation peut être évitée mais elle a l'avantage d'optimiser automatiquement la requête tout en protégeant contre les injections SQL : il serait dommage de s'en passer.
C'est lors de l'exécution que nous envoyons les paramètres à la requête. Cela a l'avantage de permettre de préparer une seule fois la requête mais en l'exécutant plusieurs fois avec des paramètres différents.
La méthode fetch() permet de récupérer uniquement l'enregistrement suivant, tandis que la méthode fetchAll() permet de tous les récupérer en une fois.

Il faut modifier toutes les requêtes de cette manière. C'est la première fois que je le fais et j'y suis parvenu sans être vraiment à ce que je fais, donc j'imagine que vous n'aurez pas trop de problèmes non plus.

Voici le code complet de Pierre-Baptiste converti à cette étape : [ FTP ] ou [ HTTP ].


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2006 Guillaume Rossolini. Aucune reproduction, même partielle, ne peut être faite de ce site et 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.