Se connecter à une base avec PDO

Première leçon du cours PHP et bases de données (PDO), en accès libre : environ 15 minutes, 3 exercices et 3 questions de quiz. C'est la leçon de base du catalogue ; dans l'espace étudiant, elle est réécrite pour ton profil.

Objectifs

  • Comprendre le rôle de PDO et des pilotes de base de données
  • Écrire un DSN pour SQLite, MySQL et PostgreSQL
  • Configurer PDO pour lever des exceptions et renvoyer des tableaux associatifs

PDODSN et options de connexionPDOException

Une application web stocke presque toujours ses données dans une base : comptes, produits, commandes… En PHP, la façon moderne et standard d’y accéder est PDO (PHP Data Objects). PDO offre la même API quel que soit le système de gestion de base de données (SGBD) : MySQL/MariaDB, PostgreSQL, SQLite, SQL Server… Chaque SGBD est géré par un pilote (pdo_mysql, pdo_pgsql, pdo_sqlite). Vous pouvez vérifier ceux qui sont installés avec php -m.

Le DSN : l’adresse de la base

On crée une connexion en instanciant la classe PDO avec un DSN (Data Source Name), puis éventuellement un utilisateur, un mot de passe et des options.

// SQLite en mémoire : idéal pour apprendre et pour les tests
$pdo = new PDO('sqlite::memory:');

// SQLite dans un fichier
$pdo = new PDO('sqlite:' . __DIR__ . '/app.sqlite');

// MySQL / MariaDB : toujours préciser charset=utf8mb4
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=boutique;charset=utf8mb4', 'app', 'secret');

// PostgreSQL
$pdo = new PDO('pgsql:host=127.0.0.1;port=5432;dbname=boutique', 'app', 'secret');

Les options indispensables

$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION, // une erreur SQL lève une exception
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,       // lignes sous forme de tableaux associatifs
    PDO::ATTR_EMULATE_PREPARES   => false,                  // vraies requêtes préparées (MySQL)
];
$pdo = new PDO($dsn, $user, $password, $options);

Depuis PHP 8.0, le mode d’erreur par défaut est déjà ERRMODE_EXCEPTION, mais l’écrire explicitement rend le code lisible et robuste. Sans exception, une requête fautive renverrait simplement false, et l’erreur passerait inaperçue.

Gérer l’échec de connexion

try {
    $pdo = new PDO($dsn, getenv('DB_USER'), getenv('DB_PASSWORD'), $options);
} catch (PDOException $e) {
    error_log($e->getMessage());          // on journalise le détail
    http_response_code(500);
    exit('Service momentanément indisponible.'); // message neutre pour l'utilisateur
}

Le message d’une PDOException peut révéler le nom de l’hôte ou de la base : on le journalise, on ne l’affiche pas. De même, le mot de passe ne doit jamais apparaître dans le code versionné : lisez-le depuis une variable d’environnement (getenv(), $_ENV) ou un fichier .env ignoré par Git.

Exécuter une première instruction

Pour une instruction sans paramètre et sans résultat (création de table, par exemple), exec() suffit. Elle renvoie le nombre de lignes affectées.

$pdo->exec('CREATE TABLE produits (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    nom TEXT NOT NULL,
    prix REAL NOT NULL
)');

Bon à savoir : depuis PHP 8.4, PDO::connect($dsn, ...) renvoie une sous-classe propre au pilote (Pdo\Sqlite, Pdo\Mysql…). new PDO(...) reste valable et c’est ce que vous rencontrerez le plus souvent. PHP 8.5 déprécie en revanche les constantes propres à un pilote déclarées sur PDO (par exemple PDO::SQLITE_ATTR_OPEN_FLAGS) : utilisez celles de la sous-classe (Pdo\Sqlite::ATTR_OPEN_FLAGS, Pdo\Mysql::ATTR_...).

En résumé : un DSN correct, des options explicites, des identifiants hors du code et une gestion d’erreur discrète. C’est la base de tout le reste du cours.

Exercices

Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.

  1. CodeDifficulté 1Sandbox serveur2 indices

    Créer une connexion configurée

    Écrivez une fonction connecter(): PDO qui renvoie une connexion SQLite en mémoire configurée avec :

    • le mode d’erreur PDO::ERRMODE_EXCEPTION ;
    • le mode de récupération par défaut PDO::FETCH_ASSOC.
    function connecter(): PDO
    {
        // À compléter
    }
  2. CodeDifficulté 2Sandbox serveur2 indices

    Créer et remplir une table

    Écrivez une fonction initialiser(PDO $pdo): void qui :

    1. crée une table clients (id INTEGER PRIMARY KEY AUTOINCREMENT, nom TEXT NOT NULL, ville TEXT NOT NULL) ;
    2. insère trois clients : Alice (Lyon), Bruno (Lille), Chloé (Lyon).

    Utilisez exec().

    function initialiser(PDO $pdo): void
    {
        // CREATE TABLE puis INSERT
    }
  3. QCMDifficulté 11 indice

    Choisir le bon DSN

    Quel DSN permet de se connecter à la base MySQL boutique sur la machine locale avec un encodage complet (accents et emojis) ?

    • mysql:host=127.0.0.1;dbname=boutique;charset=utf8mb4
    • mysql://127.0.0.1/boutique?charset=utf8
    • sqlite:boutique;charset=utf8mb4
    • mysql:host=127.0.0.1;database=boutique

Quiz de fin de leçon

  1. Que se passe-t-il, avec PDO::ERRMODE_EXCEPTION, si une requête SQL contient une erreur de syntaxe ?

    • La méthode renvoie false silencieusement
    • Une PDOException est levée
    • PHP affiche un avertissement et continue
  2. Quelle méthode utiliser pour exécuter un CREATE TABLE sans paramètre ?

    • exec()
    • fetch()
    • lastInsertId()
  3. Où ranger le mot de passe de la base de données ?

    • Dans le code PHP, en constante
    • Dans une variable d'environnement ou un fichier .env non versionné
    • Dans un commentaire HTML

La suite du cours

  1. Lire des données : query, fetch et fetchAll15 min
  2. Requêtes préparées et injection SQL20 min
  3. Insérer, modifier, supprimer et transactions20 min
  4. Organiser l'accès aux données : entités et repository20 min

PHP et bases de données (PDO) · Intermédiaire · 3 h