Leçon 6/6 10 min

Base de données SQL

Connectez PHP à une base de données avec PDO, maîtrisez le CRUD et protégez-vous contre l'injection SQL.

C'est quoi une base de données SQL ?

Une base de données, c'est un classeur organisé. Chaque table est un onglet, chaque ligne est un enregistrement, chaque colonne est un champ :

Table : utilisateurs
+----+---------+---------------------+----------+
| id | nom     | email               | role     |
+----+---------+---------------------+----------+
|  1 | Alice   | alice@exemple.fr    | admin    |
|  2 | Bob     | bob@exemple.fr      | user     |
|  3 | Charlie | charlie@exemple.fr  | user     |
+----+---------+---------------------+----------+

SQL (Structured Query Language) est le langage pour parler à la base de données : lire, ajouter, modifier, supprimer des données.

PDO : se connecter à la base

PHP utilise PDO (PHP Data Objects) pour se connecter aux bases de données. PDO fonctionne avec MySQL, PostgreSQL, SQLite... :

try {
    $pdo = new PDO(
        'mysql:host=localhost;dbname=mon_site;charset=utf8mb4',
        'utilisateur',    // nom d'utilisateur BDD
        'mot_de_passe',   // mot de passe BDD
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]
    );
} catch (PDOException $e) {
    die("Erreur de connexion : " . $e->getMessage());
}

Les deux options PDO sont importantes :

  • ERRMODE_EXCEPTION — lance une exception en cas d'erreur (au lieu de silence)
  • FETCH_ASSOC — renvoie les résultats en tableaux associatifs

CRUD : les 4 opérations

Tout ce que vous ferez avec une base de données tient en 4 opérations :

// CREATE — insérer des données
$sql = "INSERT INTO utilisateurs (nom, email, role) VALUES (?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute(['Alice', 'alice@exemple.fr', 'admin']);

// READ — lire des données
$sql = "SELECT * FROM utilisateurs WHERE role = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute(['admin']);
$admins = $stmt->fetchAll();

foreach ($admins as $admin) {
    echo $admin['nom'] . " — " . $admin['email'] . "<br>";
}

// UPDATE — modifier des données
$sql = "UPDATE utilisateurs SET role = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute(['moderator', 2]);

// DELETE — supprimer des données
$sql = "DELETE FROM utilisateurs WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([3]);

Requêtes préparées : la règle d'or

JAMAIS concaténer des variables dans une requête SQL. C'est la porte ouverte à l'injection SQL :

// ⛔ DANGER — injection SQL possible !
$sql = "SELECT * FROM utilisateurs WHERE email = '$email'";
// Un attaquant peut envoyer : ' OR 1=1 --
// → SELECT * FROM utilisateurs WHERE email = '' OR 1=1 --'
// → Renvoie TOUS les utilisateurs !

// ✅ CORRECT — requête préparée
$sql = "SELECT * FROM utilisateurs WHERE email = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$email]);
$user = $stmt->fetch();

Les ? sont des placeholders. PDO s'occupe d'échapper les valeurs — impossible d'injecter du SQL malveillant.

Exemple complet : liste d'articles

<?php
// connexion.php (à inclure partout)
$pdo = new PDO('mysql:host=localhost;dbname=blog;charset=utf8mb4',
    'root', '', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

// Lire tous les articles publiés
$stmt = $pdo->prepare("SELECT * FROM articles WHERE publie = ? ORDER BY date_creation DESC");
$stmt->execute([1]);
$articles = $stmt->fetchAll();
?>

<h1>Blog</h1>
<?php if (empty($articles)): ?>
    <p>Aucun article pour le moment.</p>
<?php else: ?>
    <?php foreach ($articles as $article): ?>
        <article>
            <h2><?= htmlspecialchars($article['titre']) ?></h2>
            <p><?= htmlspecialchars($article['extrait']) ?></p>
            <small><?= $article['date_creation'] ?></small>
        </article>
    <?php endforeach; ?>
<?php endif; ?>

Prévention de l'injection SQL

Résumé des règles de sécurité pour la base de données :

  • Toujours utiliser des requêtes préparées avec ?
  • Jamais concaténer $_GET, $_POST ou $_COOKIE dans une requête
  • Limiter les droits de l'utilisateur BDD (pas de DROP, pas de GRANT)
  • Valider les données avant la requête (type, longueur, format)

What is a SQL database?

A database is an organized filing system. Each table is a tab, each row is a record, each column is a field:

Table: users
+----+---------+---------------------+----------+
| id | name    | email               | role     |
+----+---------+---------------------+----------+
|  1 | Alice   | alice@example.com   | admin    |
|  2 | Bob     | bob@example.com     | user     |
|  3 | Charlie | charlie@example.com | user     |
+----+---------+---------------------+----------+

SQL (Structured Query Language) is the language to talk to the database: read, add, update, delete data.

PDO: connecting to the database

PHP uses PDO (PHP Data Objects) to connect to databases. PDO works with MySQL, PostgreSQL, SQLite...:

try {
    $pdo = new PDO(
        'mysql:host=localhost;dbname=my_site;charset=utf8mb4',
        'username',       // DB username
        'password',       // DB password
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]
    );
} catch (PDOException $e) {
    die("Connection error: " . $e->getMessage());
}

The two PDO options are important:

  • ERRMODE_EXCEPTION — throws an exception on error (instead of silence)
  • FETCH_ASSOC — returns results as associative arrays

CRUD: the 4 operations

Everything you do with a database fits into 4 operations:

// CREATE — insert data
$sql = "INSERT INTO users (name, email, role) VALUES (?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute(['Alice', 'alice@example.com', 'admin']);

// READ — read data
$sql = "SELECT * FROM users WHERE role = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute(['admin']);
$admins = $stmt->fetchAll();

foreach ($admins as $admin) {
    echo $admin['name'] . " — " . $admin['email'] . "<br>";
}

// UPDATE — modify data
$sql = "UPDATE users SET role = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute(['moderator', 2]);

// DELETE — remove data
$sql = "DELETE FROM users WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([3]);

Prepared statements: the golden rule

NEVER concatenate variables into a SQL query. It's an open door to SQL injection:

// ⛔ DANGER — SQL injection possible!
$sql = "SELECT * FROM users WHERE email = '$email'";
// An attacker can send: ' OR 1=1 --
// → SELECT * FROM users WHERE email = '' OR 1=1 --'
// → Returns ALL users!

// ✅ CORRECT — prepared statement
$sql = "SELECT * FROM users WHERE email = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$email]);
$user = $stmt->fetch();

The ? are placeholders. PDO handles escaping values — impossible to inject malicious SQL.

Complete example: article list

<?php
// connection.php (include everywhere)
$pdo = new PDO('mysql:host=localhost;dbname=blog;charset=utf8mb4',
    'root', '', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

// Read all published articles
$stmt = $pdo->prepare("SELECT * FROM articles WHERE published = ? ORDER BY created_at DESC");
$stmt->execute([1]);
$articles = $stmt->fetchAll();
?>

<h1>Blog</h1>
<?php if (empty($articles)): ?>
    <p>No articles yet.</p>
<?php else: ?>
    <?php foreach ($articles as $article): ?>
        <article>
            <h2><?= htmlspecialchars($article['title']) ?></h2>
            <p><?= htmlspecialchars($article['excerpt']) ?></p>
            <small><?= $article['created_at'] ?></small>
        </article>
    <?php endforeach; ?>
<?php endif; ?>

SQL injection prevention

Summary of database security rules:

  • Always use prepared statements with ?
  • Never concatenate $_GET, $_POST or $_COOKIE in a query
  • Limit permissions of the DB user (no DROP, no GRANT)
  • Validate data before querying (type, length, format)
Simulation CRUD avec un tableau
Avec l'IA

Copiez ce prompt dans Claude ou ChatGPT :

Crée une classe PHP « Database » qui encapsule PDO avec des méthodes : query($sql, $params), find($table, $id), insert($table, $data), update($table, $id, $data), delete($table, $id). Toujours avec des requêtes préparées.
Comment se connecter à une base MySQL en PHP ?
Pourquoi ne faut-il JAMAIS concaténer des variables dans une requête SQL ?
Quelle méthode PDO récupère toutes les lignes du résultat ?
Que représente le ? dans WHERE id = ? ?

Pour aller plus loin

Vous maîtrisez maintenant les fondamentaux de PHP. Voici les sujets avancés à explorer :

  • Laravel — le framework PHP le plus populaire Documentation
  • Symfony — framework d'entreprise, très utilisé en France Documentation
  • Composer — le gestionnaire de packages PHP Site officiel
  • PHP 8.x — named arguments, enums, fibers, readonly properties PHP.net
  • API REST — construire des API JSON avec PHP W3Schools

Références complètes : W3Schools PHP · PHP.net

La plomberie est installée

Félicitations. Votre bâtiment communique maintenant avec le monde extérieur — il reçoit des données, les stocke, les traite et répond. L'eau coule dans les tuyaux, les robinets fonctionnent, la chaudière chauffe.

Avec HTML (structure), CSS (façade), JavaScript (électricité) et PHP (plomberie), vous avez les 4 piliers du développement web.

La suite ? Python et Go pour élargir vos horizons au-delà du web — data science, automatisation, systèmes distribués. Les fondations sont solides. Continuez à construire.

Going further

You now master the fundamentals of PHP. Here are advanced topics to explore:

  • Laravel — the most popular PHP framework Documentation
  • Symfony — enterprise framework, widely used in Europe Documentation
  • Composer — the PHP package manager Official site
  • PHP 8.x — named arguments, enums, fibers, readonly properties PHP.net
  • REST API — build JSON APIs with PHP W3Schools

Full references: W3Schools PHP · PHP.net

The plumbing is installed

Congratulations. Your building now communicates with the outside world — it receives data, stores it, processes it and responds. Water flows through the pipes, faucets work, the boiler heats.

With HTML (structure), CSS (facade), JavaScript (electricity) and PHP (plumbing), you have the 4 pillars of web development.

What's next? Python and Go to broaden your horizons beyond the web — data science, automation, distributed systems. The foundations are solid. Keep building.

Commencer le cours Python →
Start the Python course →
Besoin d'un développeur pour votre projet ?

Réponse sous 24h — Sans engagement