Vous voulez connecter votre site PHP à une base de données ? Vous avez entendu parler des injections SQL et vous cherchez une méthode sûre pour les éviter ? Vous vous demandez quelle est la bonne façon de faire en 2025 ?
Ce guide vous explique pas à pas comment utiliser PDO (PHP Data Objects). C’est la méthode moderne, sécurisée et flexible pour toutes vos interactions avec une base de données. On va voir tout ça avec des exemples de code simples que vous pouvez réutiliser.
Pourquoi choisir PDO ? Comparatif avec `mysqli` et `mysql`
Avant, PHP proposait plusieurs extensions pour se connecter à une base de données, principalement MySQL. Les plus connues étaient `mysql` et `mysqli`. Aujourd’hui, l’extension `mysql` est totalement abandonnée car elle était trop dangereuse. Il reste donc deux choix principaux : `mysqli` et `PDO`.
PDO est sorti vainqueur car il est plus flexible et plus universel. Il fournit une interface unique pour parler à de nombreux types de bases de données, pas seulement MySQL. Le tableau ci-dessous résume rapidement les différences.
| Fonctionnalité | PDO | mysqli | mysql (obsolète) |
|---|---|---|---|
| Compatibilité SGBD | Très élevée (MySQL, PostgreSQL, SQLite, Oracle, Microsoft SQL Server…) | MySQL/MariaDB uniquement | MySQL uniquement |
| Prévention Injections SQL | Excellente (via requêtes préparées) | Bonne (via requêtes préparées) | Manuelle et risquée |
| Performance | Très bonne | Légèrement plus rapide pour MySQL | Faible |
| Syntaxe | Moderne et orientée objet | Orientée objet et procédurale | Procédurale et datée |
| Support POO | Natif (classe PDO) | Oui | Non |
Étape 1 : Se connecter à une base de données avec PDO (DSN)
La première chose à faire est d’établir la connexion. Avec PDO, on utilise un DSN (Data Source Name). C’est juste une chaîne de caractères qui décrit à quel type de base de données on veut se connecter, où elle se trouve et comment elle s’appelle.
Le format du DSN change un peu selon le système de base de données (SGBD) que vous utilisez.
- Pour MySQL : `mysql:host=localhost;dbname=nom_de_la_base`
- Pour PostgreSQL : `pgsql:host=localhost;dbname=nom_de_la_base`
- Pour SQLite : `sqlite:/chemin/vers/votre/base.db`
Pour gérer les erreurs de connexion, comme un mauvais mot de passe ou un serveur éteint, il faut toujours mettre son code de connexion dans un bloc `try…catch`. Si la connexion échoue, PDO lève une erreur de type `PDOException` que vous pouvez intercepter pour afficher un message propre au lieu d’une erreur PHP qui peut révéler des informations sensibles.
$host = ‘localhost’;
$dbname = ‘ma_base_de_donnees’;
$user = ‘root’;
$password = ‘votre_mot_de_passe’;
// Création du DSN
$dsn = « mysql:host= » . $host . « ;dbname= » . $dbname;
try {
// Création d’une instance de la classe PDO
$pdo = new PDO($dsn, $user, $password);
// Affiche un message si la connexion réussit
echo « Connexion à la base de données réussie ! »;
} catch (PDOException $e) {
// Affiche un message d’erreur si la connexion échoue
die(« Erreur de connexion : « . $e->getMessage());
}
Étape 2 : Exécuter des requêtes simples (`query` et `exec`)
Une fois connecté, vous pouvez exécuter des requêtes SQL. PDO propose deux méthodes simples pour cela : `query()` et `exec()`. La différence est simple :
query()est utilisée pour les requêtes qui retournent des résultats, comme un `SELECT`.exec()est utilisée pour les requêtes qui modifient des données (`INSERT`, `UPDATE`, `DELETE`) et retourne le nombre de lignes affectées.
Voici un exemple avec `query()` pour récupérer tous les utilisateurs.
$stmt = $pdo->query($sql);
while (($row = $stmt->fetch()) !== false) {
echo $row[‘nom’] . ‘<br>’;
}
Et un exemple avec `exec()` pour insérer un nouvel utilisateur.
$nombre_lignes_affectees = $pdo->exec($sql);
echo $nombre_lignes_affectees . ‘ utilisateur a été ajouté.’;
Étape 3 : La puissance des requêtes préparées (LA méthode sécurisée)
C’est la partie la plus importante de ce tutoriel. Les requêtes préparées sont le seul moyen fiable de se protéger contre les injections SQL. Le principe est d’envoyer la requête SQL au serveur de base de données sans les données, puis d’envoyer les données séparément. Le serveur ne les mélange jamais, ce qui rend l’injection impossible.
Le processus se déroule en trois étapes :
- `prepare()` : On prépare la requête SQL avec des marqueurs (soit des `?` soit des marqueurs nommés comme `:email`).
- `execute()` : On exécute la requête en fournissant un tableau avec les valeurs qui remplacent les marqueurs.
- `fetch()` ou `fetchAll()` : On récupère les résultats comme d’habitude.
L’utilisation de marqueurs nommés (ex: `:id`, `:email`) est souvent plus claire que les points d’interrogation, car l’ordre des valeurs dans le tableau `execute()` n’a pas d’importance.
Exemple d’un `SELECT` préparé
Ici, on cherche un utilisateur par son email. L’email vient d’une source externe, il est donc crucial de le sécuriser.
$email_utilisateur = ‘contact@exemple.com’;
// 1. On prépare la requête
$sql = ‘SELECT * FROM utilisateurs WHERE email = :email’;
$stmt = $pdo->prepare($sql);
// 2. On exécute en liant la valeur
$stmt->execute([‘:email’ => $email_utilisateur]);
// 3. On récupère le résultat
$utilisateur = $stmt->fetch();
if ($utilisateur) {
echo ‘Utilisateur trouvé : ‘ . $utilisateur[‘nom’];
} else {
echo ‘Aucun utilisateur trouvé avec cet email.’;
}
Étape 4 : Récupérer les résultats (`fetch` et `fetchAll`)
Quand votre requête `SELECT` a été exécutée, vous devez récupérer les lignes de résultats. PDO offre principalement deux méthodes pour ça :
- `fetch()` : Récupère une seule ligne de résultat à la fois. C’est parfait pour être utilisé dans une boucle `while` quand on s’attend à plusieurs résultats, car cela consomme moins de mémoire.
- `fetchAll()` : Récupère toutes les lignes de résultat d’un seul coup et les retourne dans un tableau. C’est pratique pour des résultats peu nombreux, mais attention à la mémoire si vous récupérez des milliers de lignes.
Par défaut, ces méthodes retournent un tableau indexé à la fois par le nom de la colonne et par son numéro (0, 1, 2…). Pour n’avoir que les noms de colonnes, ce qui est plus propre, on utilise le mode `PDO::FETCH_ASSOC`.
Exemple avec `fetch()` dans une boucle
$stmt = $pdo->prepare($sql);
$stmt->execute();
// On configure le mode de récupération
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo ‘Nom : ‘ . $row[‘nom’] . ‘, Email : ‘ . $row[’email’] . ‘<br>’;
}
Exemple avec `fetchAll()`
$stmt = $pdo->prepare($sql);
$stmt->execute();
// On récupère tout dans un tableau
$utilisateurs = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($utilisateurs as $user) {
echo ‘Nom : ‘ . $user[‘nom’] . ‘<br>’;
}
Étape 5 : Gérer les erreurs en PDO
Un bon code doit bien gérer les erreurs. Par défaut, PDO est en mode silencieux : si une requête SQL échoue, il ne dit rien. Ce n’est pas pratique pour déboguer. Il existe trois modes de gestion des erreurs :
PDO::ERRMODE_SILENT: (par défaut) Ne fait rien, vous devez vérifier les erreurs manuellement.PDO::ERRMODE_WARNING: Affiche un `E_WARNING` PHP.PDO::ERRMODE_EXCEPTION: Lance une `PDOException`. C’est le mode recommandé car il arrête le script en cas d’erreur et peut être capturé par un bloc `try…catch`.
On active le mode exception juste après la connexion, en utilisant la méthode `setAttribute` sur l’objet PDO. C’est une bonne pratique à adopter dans tous vos projets.
$pdo = new PDO($dsn, $user, $password);
// On active le mode d’affichage des erreurs
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Maintenant, si une requête SQL échoue, elle lèvera une exception
} catch (PDOException $e) {
die(« Erreur : « . $e->getMessage());
}
FAQ – Questions fréquentes sur PHP PDO
Quelle est la différence entre `bindValue` et `bindParam` ?
Ce sont deux méthodes pour lier des valeurs dans une requête préparée. La différence est subtile : `bindValue` lie la valeur de la variable au moment de l’appel. `bindParam` lie la variable elle-même (sa référence). Si la variable change de valeur entre le `bindParam` et le `execute`, c’est la nouvelle valeur qui sera utilisée. Pour 99% des cas, `execute()` avec un tableau est plus simple et fait le travail.
PDO est-il plus lent que `mysqli` ?
Techniquement, `mysqli` peut être une minuscule fraction de seconde plus rapide pour des requêtes sur MySQL, car il est spécialisé. Mais dans une application réelle, cette différence est totalement négligeable et invisible. Les avantages de PDO en termes de portabilité et de syntaxe claire l’emportent largement sur ce micro-gain de performance.
Comment utiliser les transactions avec PDO ?
Les transactions permettent d’exécuter un groupe de requêtes SQL. Soit elles réussissent toutes, soit elles sont toutes annulées. C’est utile pour des opérations complexes comme une commande en ligne (mettre à jour le stock ET enregistrer le paiement). Avec PDO, c’est simple :
$pdo->beginTransaction(): Démarre la transaction.$pdo->commit(): Valide toutes les requêtes si tout s’est bien passé.$pdo->rollBack(): Annule tout si une erreur est survenue.
