Tout expliqué pas à pas
Formation DWWM - 2025-2026
On va apprendre TOUT depuis zéro :
On commence par le commencement
Ce qui est dans la base de données :
Ce que fait PHP :
Le premier contact
<?php
// Informations de connexion (comme un trousseau de cles)
$host = 'localhost'; // Ou est MySQL ? (ici, sur cet ordinateur)
$dbname = 'ma_base'; // Quelle base de donnees ?
$username = 'root'; // Qui se connecte ?
$password = ''; // Mot de passe (souvent vide en local)
// Creer la connexion
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
echo "Connecte !"; // Si ca affiche, ca a marche !
?>
$host = 'localhost' → MySQL est sur CET ordinateur$dbname = 'ma_base' → On veut accéder à la base "ma_base"$username = 'root' → On se connecte en tant que "root" (admin)$password = '' → Pas de mot de passe en local (chaîne vide)new PDO(...) → Crée la connexion, stockée dans $pdo
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
│ │ │ │ │ │
│ │ │ │ │ Mot de passe
│ │ │ │ Nom utilisateur
│ │ │ Nom de la base
│ │ Serveur (localhost = cet ordi)
│ Type de BDD (mysql, pgsql, sqlite...)
Objet PDO (connexion etablie)
<?php
try {
// Essayer de se connecter
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
echo "Connexion reussie !";
} catch (PDOException $e) {
// Si ca echoue, on arrive ici
echo "Erreur : " . $e->getMessage();
die(); // Arreter le script
}
?>
try { ... } → "Essaye de faire ça"catch (PDOException $e) { ... } → "Si ça plante, fais ça"$e->getMessage() → Le message d'erreur de MySQLdie() → Arrête tout (on peut pas continuer sans BDD)
| Erreur | Signification | Solution |
|---|---|---|
| Access denied for user 'root'@'localhost' | Mauvais user ou password | Vérifier username/password |
| Unknown database 'ma_base' | La base n'existe pas | Créer la base dans phpMyAdmin |
| Connection refused | MySQL n'est pas démarré | Démarrer MySQL (XAMPP/WAMP) |
| could not find driver | Extension PDO pas activée | Activer pdo_mysql dans php.ini |
<?php
$host = 'localhost';
$dbname = 'ma_base';
$username = 'root';
$password = '';
// DSN (Data Source Name)
$dsn = "mysql:host=$host;dbname=$dbname;charset=utf8mb4";
// ^
// IMPORTANT pour les accents et emojis
// Options de configuration
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // Afficher les erreurs
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // Format tableau associatif
PDO::ATTR_EMULATE_PREPARES => false, // Vraies requetes preparees
];
try {
$pdo = new PDO($dsn, $username, $password, $options);
echo "Connexion OK !";
} catch (PDOException $e) {
die("Erreur : " . $e->getMessage());
}
?>
Récupérer des données
On a cette table "client" dans MySQL :
| id | nom | |
|---|---|---|
| 1 | Dupont | dupont@email.com |
| 2 | Martin | martin@email.com |
| 3 | Durand | durand@email.com |
Code PHP pour afficher les clients :
<?php
// 1. Connexion (deja faite avant)
// $pdo est deja connecte
// 2. Preparer la requete SQL
$sql = "SELECT * FROM client";
// ^ ^ ^
// | | Nom de la table
// | * = tout (id, nom, email...)
// Commande SQL (recuperer)
// 3. Executer la requete
$stmt = $pdo->query($sql);
// ^ ^
// | Envoie la requete a MySQL
// Resultat (objet PDOStatement)
// 4. Parcourir les resultats
while ($client = $stmt->fetch()) {
// $client = un tableau avec les donnees d'UN client
echo $client['nom'] . " - " . $client['email'] . "<br>";
}
?>
SELECT * FROM client
^ ^ ^ ^
| | | Nom de la table
| | "DEPUIS" (depuis quelle table ?)
| * = "tout" (toutes les colonnes)
"SELECTIONNE" (recupere des donnees)
$stmt = $pdo->query($sql);
^ ^ ^
| | La requete SQL
| Methode pour executer
Resultat (contient les clients)
$client = $stmt->fetch();
^ ^ ^
| | Recupere UNE ligne
| Le resultat de la requete
Tableau avec les donnees d'un client
// Exemple de ce qui est dans $client :
$client = [
'id' => 1,
'nom' => 'Dupont',
'email' => 'dupont@email.com'
]
while ($client = $stmt->fetch()) {
echo $client['nom'] . "<br>";
}
// Affiche :
// Dupont
// Martin
// Durand
$clients = $stmt->fetchAll();
// $clients est un GRAND tableau contenant TOUS les clients
foreach ($clients as $client) {
echo $client['nom'] . "<br>";
}
// Meme resultat mais tout est en memoire d'un coup
| Méthode | Quand l'utiliser | Avantage |
|---|---|---|
| fetch() | Beaucoup de résultats (1000+ lignes) | Économise la mémoire |
| fetchAll() | Peu de résultats (< 1000 lignes) | Plus simple, tout d'un coup |
fetchAll(), c'est plus simple !fetch() pour de GRANDES tables.
Expliqué très simplement
Formulaire normal :
Code PHP (DANGEREUX) :
<?php
// Recuperer ce que l'utilisateur a tape
$email = $_POST['email'];
$password = $_POST['password'];
// Construire la requete SQL
$sql = "SELECT * FROM user WHERE email = '$email' AND password = '$password'";
^ ^
On met les variables DIRECTEMENT dans le SQL
// Executer
$stmt = $pdo->query($sql);
$user = $stmt->fetch();
if ($user) {
echo "Connecte !";
} else {
echo "Erreur";
}
?>
Un utilisateur normal tape :
Un PIRATE tape :
' OR '1'='1) dans le mot de passe !Site de vente avec recherche de produits :
// Code DANGEREUX
$recherche = $_GET['q']; // Ce que l'utilisateur tape dans la recherche
$sql = "SELECT * FROM produit WHERE nom LIKE '%$recherche%'";
$stmt = $pdo->query($sql);
Recherche normale :
Attaque :
La protection expliquée simplement
<?php
// Recuperer les donnees utilisateur
$email = $_POST['email'];
$password = $_POST['password'];
// ETAPE 1 : Preparer la requete (structure avec marqueurs ?)
$sql = "SELECT * FROM user WHERE email = ? AND password = ?";
^ ^
Marqueurs (trous)
$stmt = $pdo->prepare($sql);
// ^
// "prepare" au lieu de "query" !
// ETAPE 2 : Executer avec les donnees
$stmt->execute([$email, $password]);
// ^ ^
// Donnees envoyees separement
// Position 1 Position 2
// ETAPE 3 : Recuperer le resultat
$user = $stmt->fetch();
if ($user) {
echo "Connecte !";
} else {
echo "Erreur de connexion";
}
?>
$sql = "SELECT * FROM user WHERE email = ? AND password = ?";
$stmt = $pdo->prepare($sql);
PHP envoie la STRUCTURE à MySQL (sans les données).
MySQL dit : "OK j'ai compris, tu vas me chercher un user avec 2 critères"
Les ? sont des marqueurs = places réservées pour les données
$stmt->execute([$email, $password]);
PHP envoie les DONNÉES (email et password).
MySQL remplit les ? avec ces données.
Mais MySQL sait que c'est du TEXTE, jamais du CODE !
$user = $stmt->fetch();
Récupérer le résultat (l'utilisateur trouvé, ou rien)
Au lieu de ?, on peut donner des noms :
<?php
$email = $_POST['email'];
$password = $_POST['password'];
// Marqueurs NOMMES (avec :nom)
$sql = "SELECT * FROM user WHERE email = :email AND password = :pwd";
^ ^
Marqueurs nommes
$stmt = $pdo->prepare($sql);
// Execute avec tableau associatif
$stmt->execute([
':email' => $email, // :email sera remplace par $email
':pwd' => $password // :pwd sera remplace par $password
]);
$user = $stmt->fetch();
?>
? → Plus court, mais l'ordre compte:nom → Plus clair quand il y a beaucoup de paramètres
<?php
// Formulaire de recherche de clients
$nom = $_GET['nom'] ?? ''; // Nom tape par l'utilisateur
// ❌ VERSION DANGEREUSE (ne JAMAIS faire ca !)
// $sql = "SELECT * FROM client WHERE nom LIKE '%$nom%'";
// $stmt = $pdo->query($sql);
// ✅ VERSION SECURISEE (requete preparee)
$sql = "SELECT * FROM client WHERE nom LIKE ?";
$stmt = $pdo->prepare($sql);
// Important : ajouter les % DANS le tableau execute, pas dans le SQL
$stmt->execute(["%$nom%"]);
// ^ ^
// On ajoute les % pour le LIKE
// Recuperer les resultats
$clients = $stmt->fetchAll();
// Afficher
foreach ($clients as $client) {
echo $client['nom'] . " - " . $client['email'] . "<br>";
}
?>
"%$nom%" dans execute(), pas dans le SQL !Create, Read, Update, Delete
Situation : Un nouveau client s'inscrit sur le site
<?php
// Donnees du formulaire d'inscription
$nom = $_POST['nom']; // Ex: "Dupont"
$prenom = $_POST['prenom']; // Ex: "Jean"
$email = $_POST['email']; // Ex: "jean@email.com"
// INSERT avec requete preparee
$sql = "INSERT INTO client (nom, prenom, email) VALUES (?, ?, ?)";
// ^ ^ ^ ^
// Commande INSERT Colonnes Marqueurs
// (ajouter) (quelles colonnes) (donnees)
$stmt = $pdo->prepare($sql);
$stmt->execute([$nom, $prenom, $email]);
// Recuperer l'ID du nouveau client
$newId = $pdo->lastInsertId();
echo "Client ajoute avec l'ID : $newId";
?>
INSERT INTO client → "Ajoute dans la table client"(nom, prenom, email) → "Dans ces colonnes"VALUES (?, ?, ?) → "Ces valeurs (marqueurs)"lastInsertId() → MySQL génère un ID automatique, on le récupère
AVANT l'INSERT :
| id | nom | prenom | |
|---|---|---|---|
| 1 | Martin | Paul | paul@email.com |
| 2 | Durand | Marie | marie@email.com |
APRÈS l'INSERT :
| id | nom | prenom | |
|---|---|---|---|
| 1 | Martin | Paul | paul@email.com |
| 2 | Durand | Marie | marie@email.com |
| 3 | Dupont | Jean | jean@email.com |
✅ Nouvelle ligne ajoutée avec ID = 3 (auto-généré)
Situation : Le client change son email
<?php
// Donnees du formulaire de modification
$id = $_POST['id']; // Ex: 3 (quel client ?)
$nouvelEmail = $_POST['email']; // Ex: "nouveaumail@email.com"
// UPDATE avec requete preparee
$sql = "UPDATE client SET email = ? WHERE id = ?";
// ^ ^ ^ ^
// Commande Quoi Nouvelle Condition
// UPDATE changer valeur (quel client)
$stmt = $pdo->prepare($sql);
$stmt->execute([$nouvelEmail, $id]);
// Verifier si ca a marche
$nb = $stmt->rowCount(); // Nombre de lignes modifiees
if ($nb > 0) {
echo "Email modifie !";
} else {
echo "Aucun client trouve avec cet ID";
}
?>
WHERE, TOUS les clients auraient le même email !WHERE id = ?
Situation : Le client ferme son compte
<?php
// ID du client a supprimer
$id = $_GET['id']; // Ex: 3
// DELETE avec requete preparee
$sql = "DELETE FROM client WHERE id = ?";
// ^ ^ ^
// Commande Table Condition (quel client)
// DELETE
$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);
// Verifier
$nb = $stmt->rowCount();
if ($nb > 0) {
echo "Client supprime";
} else {
echo "Client introuvable";
}
?>
WHERE → DELETE FROM clientWHERE pour cibler UN client !
| Opération | SQL | Code PHP |
|---|---|---|
| CREATE | INSERT INTO | $pdo->lastInsertId() pour l'ID |
| READ | SELECT | fetch() ou fetchAll() |
| UPDATE | UPDATE...SET...WHERE | rowCount() pour vérifier |
| DELETE | DELETE...WHERE | rowCount() pour vérifier |
prepare() et execute() !new PDO())SELECT + fetch())prepare() + execute()prepare() pour les variablestry/catch
Vous êtes prêts à coder avec des bases de données ! 🚀
🐘 La pratique, c'est maintenant !
Faites des exercices, faites des erreurs, apprenez ! 💪