PHP 6 et PDO : Prévoyer l'avenir

Publié le 13 mai 2008 par Dave Lizotte
PDO, vous connaissez ? Pour certain oui, mais pour la plus part d'entrevous cela ne représente que 3 lettres. Alors qu'est-ce que PDO ? Lisez le tutoriel qui suit et vous serez en mesure de répondre à cette question après lecture et vous serez aussi en mesure d'utiliser PDO par vous même.

Qu'est-ce que PDO ?

PDO est une interface qui est apparue dans les premières versions de PHP 5. Cette interface vise à améliorer l'interaction avec les bases de données sans avoir à vous préoccuper du SGBD qui est utilisé derrière. Ainsi, il vous sera possible de créer un code qui fonctionne autant sous MySQL que sous Oracle, SQL ou ODBC. On peut déjà entrevoir toutes les possibilités qui s'offriront à nous. Les jours de mysql_query et compagnie sont comptés!
 

Le Hic ?

Tout cela semble bien rose, mais la réalité en est un peu autrement. Un des seuls problèmes que cette interface apporte porte sur le respect des standards. Chaque SGBD à ses propres standards et chacun d'entre eux interprète une sélection de données de manière différente. C'est donc dire que pour une même sélection de données, pour chaque SGBD, on se retrouve avec une requête différente. Cela fait en sorte que pour chaque SGBD, le programmeur devra avoir écrit les requêtes appropriées.
  Par contre, beaucoup de requêtes n'auront pas besoin d'être réécrite de par le mécanisme qui fonction derrière PDO et certaine plus spécifique devront l'être. De la un inconvénient qui se transforme en avantage!
 

Avantages

Pour ce qui est des autres avantages, on voit apparaître la gestion des exceptions et le fait que PDO est un objet. Alors si vous n'êtes pas familiarisé avec la programmation orientée objet, il sera temps pour vous de faire le saut.  

Connexion au SGBD

Voici ici comment vous connectez à votre base de données grâce à PDO :
  <?php
   $PARAM_hote='localhost'; // le chemin vers le serveur
   $PARAM_port='3306';
   $PARAM_nom_bd='sdz'; // le nom de votre base de données
   $PARAM_utilisateur='root'; // nom d'utilisateur pour se connecter
   $PARAM_mot_passe=''; // mot de passe de l'utilisateur pour se connecter
   $connexion = new PDO('mysql:host='.$PARAM_hote.' ; port='.$PARAM_port.' ; dbname='.$PARAM_nom_bd ,  $PARAM_utilisateur , $PARAM_mot_passe);
?>
Rien de bien compliqué! Cela ressemble jusqu'ici beaucoup à mysql_connect(). Ajoutons maintenant la gestion des exceptions.
 

Gestion des exceptions

Avec PHP 6, la gestion des exceptions sera au coeur de notre programmation. Avec PDO, il est extrêmement facile de gérer les exceptions générées par votre SGBD. Voici comment cela fonctionne :
  <?php
   try{
      $connexion = new PDO('mysql:host='.$PARAM_hote.' ; port='.$PARAM_port.' ; dbname='.$PARAM_nom_bd ,  $PARAM_utilisateur , $PARAM_mot_passe);
   }
   catch(Exception $e){
      echo 'Erreur : '.$e->getMessage().'<br />';
      echo 'N° : '.$e->getCode();
   }
?>
Vous aurez alors l'affichage de l'erreur, le catch est chargé d'intercepter une éventuelle erreur apparue dans le try : vous pouvez donc très bien mettre un arrêt du script comme ceci :    <?php
try
{
   $connexion = new PDO('mysql:host='.$PARAM_hote.' ; dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
}
 
catch(Exception $e)
{
   echo 'Une erreur est survenue !';
   die();
}
?>
Vous pouvez mettre un traitement de l'erreur comme vous voulez.

Exécuter votre première requête grâce QUERY et EXEC

PDO fait la distinction entre deux familles de requêtes :
  • Les requêtes de sélection (SELECT) > Query
  • Les requêtes d'exécution (INSERT, UPDATE, DELETE) > EXEC


Utilisation de la méthode : EXEC

Supposons que nous souhaitons modifier le mot de passe d'un membre de votre intranet :
  <?php
   $connexion = new PDO("mysql:host=$PARAM_hote ; dbname=$PARAM_nom_bd", $PARAM_utilisateur, $PARAM_mot_passe); // connexion à la BDD
    
   $connexion->exec("UPDATE membres SET password='12345' WHERE login='XYZ'");
?>
La requête ici sera bel et bien effectué, mais on peut en savoir plus sur le résultat de cette requête soit le nombre de ligne affecté par la requête :
  <?php
   $nombre_changement = $connexion->exec("UPDATE membres SET password='12345'"); // On modifie ici le mot de passe de tous les utilisateurs
   echo "La requête à modifié : $nombre_changement lignes.";
?>


Utilisation de la méthode : query

Supposons ici que nous voulons récupérer tous les login de notre portail :
  <?php
   $connexion = new PDO("mysql:host=$PARAM_hote ; dbname=$PARAM_nom_bd", $PARAM_utilisateur, $PARAM_mot_passe); // Connexion à la BDD
    
   $resultats = $connexion->query("SELECT login FROM membres ORDER BY login ASC");
   $resultats->setFetchMode(PDO::FETCH_OBJ); // On demande a l'objet PDO de nous retourner le résultat sous forme d'objet
   while( $ligne = $resultats->fetch() ) // On récupère la liste des login
   {
      echo 'Utilisateur : '.$ligne->login.'<br />'; // On affiche les login
   }
   $resultats->closeCursor(); // On ferme le curseur des résultats
?>
Deux choses ici peuvent porter à confusion :
  • setFetchMode : Permets d'indiquer sous quel format on souhaite récupérer les résultats de la requête précédente. Il existe plusieurs méthodes qui sont les suivantes : PDO::FETCH_ASSOC, PDO::FETCH_BOTH, PDO::FETCH_OBJ, ..., le mieux étant encore de lire la documentation pour savoir lequel vous préférerez utiliser. Personnellement si vous êtes habitué avec la commande mysql_fetch_object, PDO::FETCH_OBJ sera certainement la méthode que vous retiendrez.
  • closeCursor : Permets de fermer le curseur associé à un jeu de résultats, il doit donc être fermé une fois que vous avez fini de récupérer les résultats, et également être fermé avant toute autre requête. Il vous est donc conseillé de le mettre, sinon vous risquez des erreurs.
** En cas d'erreur de la requête, le résultat ne sera pas un objet, mais un booléen valant false qui représente alors une mauvaise requête ou un curseur qui n'a pas été fermé.
 

La méthode Prepare

La méthode Prepare comme sont nom l'indique, prépare une requête SQL à être exécutée en offrant la possibilité de mettre des marqueurs qui seront substitués lors de l'exécution de celle-ci.
  Il existe deux types de marqueurs qui sont respectivement « ? » et les marqueurs nominatifs. Ces marqueurs ne sont pas mélangeables : donc pour une même requête, il faut choisir l'une ou l'autre des options.
 

Avantages de cette méthode :

  • Optimisation des performances pour des requêtes appelées plusieurs fois
  • Protection des injections SQL (plus besoin de le faire manuellement)

Exemple sans marqueur :

Imaginons que nous voulons récupérer une fois de plus, la liste des login.    <?php
   $requete_prepare = $connexion->prepare("SELECT login FROM membres"); // On prépare la requête
   $requete_prepare->execute();
   while($lignes=$requete_prepare->fetch(PDO::FETCH_OBJ))
   {
      echo $lignes->login.'<br />';
   }
?>

Exemple avec marqueur nominatif :

Imaginons maintenant que nous voulons un login bien précis.    <?php
   $requete_prepare=$connexion->prepare("SELECT identifiant FROM membres WHERE ID_membre = :id");
   $requete_prepare->execute(array(':id' => 1));
   $lignes=$requete_prepare->fetch(PDO::FETCH_OBJ);
   echo $lignes->identifiant.'<br />';
?>
Il est possible d'avoir plus d'un marqueur. Dans ces cas, il faut les rajouter dans la requête et dans execute.
 

Exemple avec marqueur « ? » :

Nous voulons toujours récupérer notre identifiant unique.   <?php
   $requete_prepare=$connexion->prepare("SELECT identifiant FROM membres WHERE ID_membre = ? ");
   $requete_prepare->execute(array(1));
   $lignes=$requete_prepare->fetch(PDO::FETCH_OBJ);
   echo $lignes->identifiant.'<br />';
?>

Sécuriser vos requêtes sans utiliser les requêtes préparées

Comme nous l'avons vu précédemment, il est possible de préparer une requête, ce qui va la sécuriser sans intervention de votre part. Cependant certaines fois, il vous sera impossible de préparer vos requêtes. Dans ces cas, nous pourrons aussi facilement sécuriser le tout grâce à la méthode « quote » :
  <?php
   $Connexion = new PDO(...); // Ouverture d'une connection
   $Connexion->query("SELECT id_membre FROM membres WHERE login = ".$Connexion->quote($login, PDO::PARAM_STR));
?>
La méthode quote, provenant de notre objet connexion permet de sécurisé notre paramètre. Cette méthode prend 2 arguments : Le premier obligatoire représente la valeur à protéger, et le second optionnel, représente le type de la valeur à protéger. Cette valeur peut-être :
  • PDO::PARAM_STR : Chaîne de caractères
  • PDO::PARAM_INT : Integer de SQL
  • PDO::PARAM_NULL : NULL de SQL
  • PDO::PARAM_BOOL : Booléen
  • PDO::PARAM_LOB : Objet large de SQL
** Lorsque vous utilisez cette méthode, n'englobez aucune valeur avec '', la méthode quote se le fera pour vous si nécessaire. ** Par défaut, si vous ne spécifiez pas de deuxième argument, la valeur PDO::PARAM_STR sera utilisée.
Voilà, cela fait une tour d'ensemble de ce qu'est PDO. Bien sûr, nous n'avons fait qu'effleurer le sujet. Il vous suffit alors de vous y plonger pour y voir toutes les possibilités de celui-ci.