Programmation Web Avancée

Blogue

Les cours

Connexion à Oracle ou MySQL avec PDO


Rédigé par , le
Il y a plusieurs avantages à utiliser une approche MVC pour le développement d'applications ou de sites Web. L'un de ces avantages est la séparation des couches et donc la limitation du couplage (dépendance) entre les classes.

De façon générale, pour un site Web on a :
- la vue : HTML, CSS, XML/XSLT
- le modèle : Accès aux données via des requêtes à un serveur de base de données (SQLite, MySQL, Oracle, Sybase, ...)
- le contrôleur : Logique du site Web, intermédiaire entre la vue et le modèle

Si pour une raison ou une autre, il faut changer de base de données en cours de route (Oracle à MySQL par exemple), le modèle sera la seule couche qui sera touché par le changement. En effet, la vue et le contrôleur ne jouent jamais directement avec l'accès aux données. On parle alors de l'encapsulation du modèle.

Malgré tout, changer de base de données pour une application reste désagréable. Surtout si on utilise les méthodes PHP de base comme : mysql_connect, oci_new_connect, oci_bind_by_name, mysql_query, etc. En effet, pour passer de Oracle à MySQL, il faudra aller dans chaque méthode/fonction du modèle et modifier les références aux fonctions Oracle.

Changer les appels à oci_new_connect pour des appels à mysql_connect
Changer les appels à oci_execute pour des appels à mysql_query
etc.

Afin d'éviter ce genre de problème, on peut utiliser la librairie PDO. Celle-ci permet de faire de l'abstraction de base de données. En utilisant PDO, on n'utilise plus les méthodes PHP de base pour avoir accès à nos données (i.e. oci_new_connect, ...). On laisse la responsabilité à PDO de se plier au protocole de communication avec les SGBD (Système de Gestion de Base de Données).

Exemple de connexion avec PDO

MySQL

$connection = new PDO("mysql:host=localhost;dbname=ma_bd_mysql", 
                      "usager", "motDePasse"); 
Oracle
$connection = new PDO("oci:dbname=//ellis/DECINFO.edu", 
                      "r3a9xyz", "motDePasse"); 

// Ici, "ellis" est le host/domaine, et 
// DECINFO.edu est le SERVICE_NAME.

Pour le reste, tout est pareil, que l'on soit en MySQL ou en Oracle :

Exemple de SELECT
$statement = $connection->query('SELECT ID, USERNAME FROM USERS');  
$statement->setFetchMode(PDO::FETCH_ASSOC);
  
while($row = $statement->fetch()) {  
        echo $row['ID'] . " : " . $row['USERNAME'] . "<br/>";  
} 

Exemple de INSERT
$id  = 5;
$username = "myUsername";
$password = "motDePasse";
$statement = $connection->prepare("INSERT INTO USERS(ID, NAME, PWD) ".
                                  "VALUES(?, ?, ?)");
$statement->bindParam(1, $id);  
$statement->bindParam(2, $username);  
$statement->bindParam(3, $password); 
$statement->execute(); 

Exemple de DELETE
$id  = 5;
$statement = $connection->prepare('DELETE FROM USERS WHERE ID = ?');  
$statement->bindParam(1, $id);  
$statement->execute(); 


Comme le montrent ces exemples, il n'y a aucune référence vers des méthodes Oracle ou MySQL. Bref, à part pour la ligne de connexion, on a aucune idée sur quelle base de données on interagi.

PDO est simple à utiliser et offre beaucoup. On vous demande de prendre un projet et de le mettre en MySQL au lieu de Sybase ? Pas de problème, on change la ligne de connexion et c'est terminé ! La plupart des fonctions du modèle n'auront pas à être modifiées. Évidemment, vous aurez à refaire une base de données Sybase (CREATE TABLE, ...) pour que le site puisse s'y connecter.

Il faut aussi ajouter que par défaut, les méthodes de bases dans PHP  ne supporte pas les "prepared statement" pour MySQL. Donc pas de binding des variables. Par conséquent, si on ne contrôle pas les variables PHP qui vont dans le mysql_query, on est vulnérable au SQL INJECTION. PDO remédie donc à cet inconvénient.

Si, lorsque vous développez et testez, vos erreurs de requêtes ne sont pas affichées à l'écran, ajoutez ces deux commandes après l'ouverture de votre connexion :
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Ha oui ! Il ne faut pas oublier d'activer le(s) module(s) PDO dans php.ini pour pouvoir l'utiliser.

Les commentaires sur cet article
Par : anonymous
2011-10-07 03:31:15

Pour le fetch dans le cas de ton select, le plus juste c'est un fetchAll si non il te retournera un seul enregistrement et alors ton while n'a aucune utilité.

Par : Frédéric
2011-10-07 09:55:38

@anonymous

En fait, le fetch() retournera une ligne à la fois. On peut donc en faire une itération avec un while pour parcourir le résultat de la requête.

Il y a un désavantage à utiliser le fetchAll(). Imaginons un résultat de requête retournant 1000 enregistrements. Le fetchAll() construira directement un tableau de 1000 enregistrements en RAM. Avec un fetch(), on peut parcourir un enregistrement à la fois, sans consommer trop de ressources sur le serveur

Par : mld
2013-12-04 10:35:20

Merci pour ce resumé

Par : DEME
2016-02-25 05:09:47

Merci pour le résume mais pour les champs de type clob au lieu d'afficher le contenu il affiche Resource id #2

Par : Frédéric
2016-02-25 08:00:21

@DEME

En effet, mais je crois que tu peux utiliser la fonction stream_get_line() pour avoir le texte.

Ajouter votre commentaire
(facultatif)
(facultatif et non divulgé)
Captcha image
Prenez le nombre affiché et faites moins 1.
 
Blog  

Les articles


Pour envoyer une demande d'assistance à l'enseignant, cliquez ici