C'est quoi PDO ?

Disponible depuis la version 5.1 de PHP PDO ( PHP DATA OBJECT ) , cette extention permet de développer des applications sans se préoccuper du SGBD qui sera utilisé ... Ainsi , si pour une raison X ou Y vous devez changer de SGBD , seuls quelques paramètres dans votre seront à modifier , vous ne devrez plus réécrire toutes vos requetes .

PDO est ecrit en C , donc plus performant que PEAR DB ou AdoBD , et donne de nombreuses possibilités au développeur , comme les requêtes préparé , transactions ect ...

Premier contact:

Nous allons voir sous forme d'exemples , différentes façons d'utiliser PDO.

Se connecter à une base de données :

//définition des variables de connexion
$user = "toto";
$pwd = "password";

//en fonction du driver
//mysql:
	try{
	   $instancePDO = new PDO("mysql:host=127.0.0.1;dbname=mabase,$user,$pwd");
	} catch (PDOException $e)
	{
		die("Erreur ! : ".$e->getMessage() );
	}
//pgsql:
	try{
	    $instancePDO = new PDO("pgsql:host=127.0.0.1 port=5432 dbname=mabase $user $pwd");
	} catch (PDOException $e)
	{
		die("Erreur ! : ".$e->getMessage() );
	}
//oracle
	try{
	    $instancePDO = new PDO("oci://127.0.0.1:$port/mabase");
	} catch (PDOException $e)
	{
		die("Erreur ! : ".$e->getMessage() );
	}

Les requêtes simples:

A partir de maintenant , je considère être connecté sur une base mysql.

Ici , rien ne change , nous allons utiliser des requêtes mysql standard , la seule différence réside au niveau de la façon dont nous allons envoyer ces requêtes au serveur .

Pour ces tâches , nous allons utiliser les méthodes :

  • exec()
  • query()
exec():

exec sera utilisé pour les requêtes qui ne retournent pas de résultat tel que : INSERT UPDATE DELETE En revanche , exec retourne le nombre de lignes affectées par la requête.

query():

query lui est utilisé pour toutes les requêtes qui renvoient un résultat tel que : SELECT EXPLAIN SHOW DESC cette méthode renvoie une instance de la classe PDOStatement qui utilise le motif itérateur (permet de lire votre objet comme un tableau avec foreach)

Pour résumer :

INSERT => exec()
UPDATE => exec()
DELETE => exec()
SELECT => query()
EXPLAIN => query()
SHOW => query()
DESC => query()

Examples:

SELECTION:

$sql = "SELECT * FROM table LIMIT 10";
$Res = $instance->query($sql);

$Tabres = $Res->fetchAll(PDO::FETCH_ASSOC);
var_dump($Tabres);

l'argument de fetchAll peut être :

PDO::FETCH_ASSOC
PDO::FETCH_BOTH (par defaut)
PDO::FETCH_OBJ

Resultats:

PDO::FETCH_ASSOC

Array
(
    [0]  =>  Array
        (
            [champ1]  =>  valeurA
            [champ2]    =>  valeurB
        )
)

PDO::FETCH_BOTH

Array
(
    [0]  =>  Array
        (
            [champ1]  =>  valeurA
            [0]  => valeurA
            [champ2]    =>  valeurB
            [1]  =>  valeurB
        )
)

PDO::FETCH_OBJ

Array
(
    [0]  =>  stdClass Object
        (
            [champ1]  =>  valeurA
            [champ2]    =>  valeurB
        )
)

SUPPRESSION:

$sql = "DELETE FROM table WHERE etat=1";
$retour = $instance->exec($sql);
print_r($retour);
Resultats:
//Si une erreur est srvenue
FALSE

//Si aucune ligne de table possede son etat = 1
0

//Si plusieurs lignes ont etat = 1 ex:10 lignes
10

Sécurité:

Pour éviter les injections SQL , il faut toujours échapper les données entrantes apres les avoir vérifiées . PDO nous donnes plusieurs façons de procéder ,

La première , est la méthode quote() qui permet d'échapper les chaînes entrantes dans votre base de données , Ensuite , une autre façon de faire , est d'utiliser des requêtes paramétrés , qui n'ont plus besoin d'être échappées , ce qui soulage la conscience du développeur ... et liber son esprit :-) . Nous verrons plus loin comment fonctionne les requêtes paramétrées.

Les transactions:

Les transactions , permettent d'effectuer plusieurs requêtes , Mais de valider celle-ci uniquement si aucune erreurs n'a été détecté , dans le cas contraire , on annule tout ....

Les méthodes qui vont nous servir pour les transactions sont les suivantes :

beginTransaction()
commit()
rollBack()

Je pense que le mieux est d'utiliser un try catch comme ceci :

Exemple:

//La gestion d'erreur doit être en mode exception on y reviendra plus tard
$instancePDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$instancePDO->beginTransaction();
try{

    $sql = "INSERT INTO ... ... ";
    $instancePDO->exec($sql);

    $sql = "DELETE FROM ......";
    $instancePDO->exec($sql);

    //si tous se passe bien
    $instancePDO->commit();

} catch (Exception $e) {

    //annule les requetes en cas d'erreur
    $instancePDO->rollBack();

    echo $e->getMessage();
}

Ainsi si une erreur se produit , sur une des requêtes , dans le bloc try , toutes actions effectuées auparavant , sera annulé , et l'on affichera le message d'erreur .

Vous avez certainement remarqué l'appel à la méthode setAttribute en haut du code , cette méthode , permet de changer le gestionnaire d'erreur de PDO . Il y a trois modes possible:

  • mode silencieux , ne pas afficher les erreurs : (defaut)

PDO::ATTR_ERRMODE,PDO::ERRMODE_SILENT

  • mode classique , affiche un warning:

PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING

  • mode exception , lance une exception:

PDO::ATTR_ERRMODE,PDO_ERRMODE_EXCEPTION

Plusieurs méthodes sont aussi disponible pour consulter les informations sur une erreur survenue , par exemple : errorCode()
errorInfo()
disponibles même en mode silencieux !

Les requêtes préparées:

Si vous avez une requête à exécuter de nombreuses fois dans votre script , celle-ci sera à chaque fois , analysé , précompilé optimisé puis exécuté , alors que si vous utilisez une requête préparé , ou seuls les paramètres changent , alors votre requête sera uniquement exécuté , à partir de la seconde fois , ce qui peut être un gain important en terme de performances ...

création d'une requête préparé:

Voilà à quoi ressemble une requête préparée :

$sql = 'INSERT INTO matable (champA, champB) VALUES (?, ?);
ou
$sql = 'INSERT INTO matable (champA, champB) VALUES (:valA, :valB);
puis 
$inststPDO = $instancePDO->prepare($sql);

La méthode prepare() permet de donner votre requête à analyser au SGBD, et renvoie une instance de PDODtatement , tout comme la méthode query() .

Ensuite , il vous faut lier vos données à votre requête. Il existe deux façons simples de le faire . Soit directement , à l'exécution de votre requête , comme ceci :

$valA = "titi";
$valB = "toto";

(array)$param = array(
           ':valA'=>$valA,
           ':valB'=>$valB
         );

$inststPDO->execute($param);

Ensuite , l'on peut aussi utiliser la méthode bindParam() qui lie une variable à un paramètre :

$valA = "titi";
$valB = "toto";

$inststPDO->bindParam(':valA',$valA);
$inststPDO->bindParam(':valB',$valB);

//enregistrement1
$inststPDO->execute();

$valA = "tata";
$valB = "tutu";

//enregistrement2 avec tata tutu
$inststPDO->execute();

Fermeture d'une ressource

En mysql , par exemple , pour libérer les ressources d'une requête , nous utilisions mysql_free_result() Et bien avec PDO , il nous suffit de spécifier notre instance PDOStatement à NULL

$inststPDO = NULL;

Voilà pour cette première approche à PDO , de nombreuse autres subtilités existent , n'hésitez pas à chercher plus loin ...

Cette article à été ecrit avec les références suivantes :