PDO

Intro

L’extension PHP Data Objects (PDO) définit une excellente interface pour accéder à une base de données depuis PHP. Chaque pilote de bdd implémenté dans l’interface PDO peut utiliser des fonctionnalités spécifiques de chacune des bases de données en utilisant des extensions de fonctions.

Notons que l’on ne peut exécuter aucune fonction de bdd en utilisant l’extension PDO par elle-même ; il faut utiliser un driver PDO spécifique à la bdd.

PDO fournit une interface d’abstraction à l’accès de données, ce qui signifie que l’on peut utiliser les mêmes fonctions pour exécuter des requêtes ou récupérer des données quelque soit la la bdd utilisée. Il ne réécrit pas le SQL, n’émule pas des fonctionnalités manquantes.

PDO fonctionne depuis PHP 5.

Constantes pré-définies

Ces constantes sont définies par cette extension. (PHP >= 5.1)

liste des constantes

Connexions et gestionnaire de connexion

Connexion

Les connexions sont établies en créant des instances de la classe de base de PDO. Peu importe quel driver on utilise ; on utilise toujours le nom de la classe PDO. Le constructeur accepte des paramètres pour spécifier la source de la base de données et optionnellement, le nom d’utilisateur et le mot de passe.

ex:

	$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
	

Lorsque la connexion à la base de données a réussi, une instance de la classe PDO est retournée au script. La connexion est active tant que l’objet PDO l’est.

Gestion des erreurs

S’il y a des erreurs de connexion, un objet PDOException est lancé. On peut l’attraper, ou laisser le gestionnaire global d’exception défini via la fonction set_exception_handler() la traiter.

ex : gestion des erreurs

	try{
		$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
		// ...
	} catch(PDOException $e){
		print "erreur : ".$e->getMessage();
		die();
	}
	

Avertissement si l’application n’attrape pas les exceptions, l’action par défaut du moteur zend est de terminer le script et d’afficher une trace. Cette trace devrait révéler des détails complets sur la connexion à la base de données, y compris le mot de passe.

Fermer une connexion

Pour clore une connexion, on doit détruire l’objet PDO en s’assurant que toutes ses références sont effacés. On peut le faire en assignant NULL à la variable gérant l’objet.

	$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
	// utilisation de la connexion
	//et fermeture
	$bdh = null
	

Si on ne le fait pas explicitement, PHP fermera automatiquement la connexion lorsque le script arrivera à la fin.

Connexion persistantes

Beaucoup d’appli web utilisent des connexions persitantes aux serveurs de bdd. Les connexions persistantes ne sont pas fernmées à la fin du script, mais sont mises en cache et réutilisées lorsqu’un autre script demande une connexion en utilisant les mêmes paramètres. Le cache des connexions persistantes nous permet d’éviter d’établir une nouvelle connexion à chaque fois qu’un script doit accéder à un bdd, rendant l’application plus rapide.

	$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
	PDO::ATTR_PERSISTENT => true
	));
	

Transactions et validation automatique

Avant d’exécuter des requêtes, il faut comprendre comment PDO gère les transactions. Les transactions offrent 4 fonctionnalités majeurs : Atomicité, Consistance, Isolation et Durabilité (ACID). En d’autres termes, n’importe quel travail mené à bien dans une transaction, même s’il est effectué par étapes, est garanti d’être appliqué à la base de données sans risque, et sans interférence pour les autres connexions, quand il est validé. Le travail des transactions peut également être automatiquement annulé à la demande (en supposant que l’on n’a rien validé), ce qui rend la gestion des erreurs bien plus simple dans les scripts.

Les transactions sont typiquement implémentées pour appliquer toutes les modifications en une seul fois. Les transactions rendent les scripts plus rapides et potentiellement plus robustes.

Cependant toutes les bdd ne supportent pas les transactions, donc PDO doit s’exécuter en mode “autocommit” lorsque on ouvre la connexion pour la première fois. Le mode “autocommit” signifie que toutes les requêtes ont leurs transactions implicites, si la bdd le supporte ou aucune transaction si la bdd ne le supporte pas.

http://php.net/manual/fr/pdo.transactions.php

Requêtes préparées et procédures stockées

La plupart des bdd supportent le concept des requêtes préparées. Celles-ci offrent deux fonctionnalités essentielles :

  • La requête ne doit être analysée (ou préparée) qu’une seule fois, mais peut être exécutée plusieurs fois avec des params identiques ou différents. Lorsqu’une requête est préparée, la bdd analyse, compile et optimise son plan pour l’exécuter. Ainsi lorsqu’on exécute une req plusieurs fois, ce processus n’est pas répété. Bref, les requêtes préparées utilisent mois de ressources et s’éxecutent plus rapidement.
  • Les paramètres pour préparer les requêtes n’ont pas besoin d’être entre guillemets. Ainsi cela empêche les injections SQL.

Les req. prépa. sont tellement pratiques que c’est l’unique fonctionnalité que PDO émule pour les drivers qui ne les supportent pas.

ex :

	<?php
	$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
	$stmt->bindParam(':name', $name);
	$stmt->bindParam(':value', $value);

	// insertion d'une ligne
	$name = 'one';
	$value = 1;
	$stmt->execute();

	// insertion d'une autre ligne avec des valeurs différentes
	$name = 'two';
	$value = 2;
	$stmt->execute();
	?>
	

ex utilisant les marqueurs ?

	$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
	$stmt->bindParam(1, $name);
	$stmt->bindParam(2, $value);
	$stmt->execute();
	

en intégrant les paramètres directement dans execute

	$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
	$stmt->execute(array($_GET['name']));
	$row = $stmt->fetch()
	

Tricks and tips