Aller au contenu
M07 · C. Manipuler les données

Ajouter, modifier, supprimer : le CRUD complet

Les quatre opérations d'une page d'administration (Create, Read, Update, Delete) avec PDO, un formulaire qui sert à la fois à créer et à modifier, la validation côté serveur, le modèle « POST puis redirection » et les erreurs de contraintes.

1Situer

L'équipe de Souk Atlas veut gérer ses catégories sans ouvrir phpMyAdmin : une liste, un bouton Ajouter, un lien Modifier sur chaque ligne, un bouton Supprimer. Ces quatre gestes forment le CRUD, le cœur de presque toutes les applications de gestion.

2Comprendre

Le CRUD des catégories, page par page
index.php · Catégories Poterie (4)✎ 🗑 Cosmétique (4)✎ 🗑 Textile (4)✎ 🗑 Bijoux (0)✎ 🗑 Maroquinerie (0)✎ 🗑 Impossible de supprimer : produits liés requête envoyée GET index.php SELECT … 200 OK R

index.php (Read) : SELECT des catégories, avec un lien Modifier et un bouton Supprimer sur chaque ligne.

1 / 5

Les quatre opérations

Une organisation simple, une page par opération :

FichierMéthodeRôle
index.phpGETliste des lignes, avec liens et boutons
ajouter.phpPOSTINSERT, puis retour à la liste
modifier.php?id=4GET puis POSTformulaire pré-rempli, puis UPDATE
supprimer.phpPOSTDELETE, puis retour à la liste

Les opérations qui modifient la base passent toujours par POST. Un GET (un lien, une adresse tapée) ne doit que lire.

Créer : valider, insérer, rediriger

Modifier : le formulaire pré-rempli

La page de modification fait deux choses selon la méthode :

  • en GET (modifier.php?id=4), elle lit la ligne et pré-remplit le formulaire avec value="<?= htmlspecialchars(...) ?>" ;
  • en POST, elle exécute l’UPDATE avec l’identifiant reçu dans un champ caché, puis redirige.
$req = $pdo->prepare('UPDATE categories SET nom = :nom WHERE id = :id');
$req->execute(['nom' => $nom, 'id' => $id]);
echo $req->rowCount() . ' ligne modifiée';

Avec MySQL, rowCount() vaut 0 si la ligne existe mais que la nouvelle valeur est identique à l’ancienne : MySQL ne compte que les lignes réellement changées.

Supprimer : la base peut refuser

Une catégorie utilisée par des produits ne peut pas être supprimée : la clé étrangère produits.categorie_id la protège (module 06). MySQL répond par une erreur, et PDO lance une exception qu’on attrape pour afficher un message clair.

Exemple simple

Le carnet d'adresses

Dans le carnet du téléphone, on ajoute un contact (Create), on le consulte (Read), on corrige son numéro (Update), on le supprime (Delete). Chaque écran d'administration répète ces quatre gestes sur une table.

Exemple simple

Le ticket de caisse

Une fois le paiement validé, la caissière vous tend le ticket et passe au client suivant. Si vous rafraîchissez la page juste après un envoi, le navigateur ne doit pas « repayer » : d'où la redirection après chaque POST.

3Manipuler

La liste des catégories et l'ajout fonctionnent déjà (lisez ajouter.php, c'est le modèle). Écrivez la modification et la suppression.
Pas à pas dans le lab ↗ Cliquez sur Exécuter : PHP 8.3 démarre dans votre navigateur (environ 5 Mo à télécharger, une seule fois).

La page s'affichera ici.

Le navigateur demandera /index.php au serveur, qui exécutera le PHP et renverra du HTML.

Entre le navigateur et le serveur aucun échange pour l'instant

Consignes 0 / 3

  1. Renommer Bijoux en « Bijoux berbères » enregistre la modification puis revient à la liste
  2. Supprimer Bijoux (aucun produit) l'enlève de la base
  3. Supprimer Poterie (4 produits) affiche « Impossible de supprimer » et la garde

4Pratiquer

Exercice 1 · Un seul formulaire pour créer et modifier

Fusionnez ajouter.php et modifier.php en un fichier form.php : sans id, il crée ; avec ?id=, il pré-remplit et met à jour.

Voir le corrigé
<?php
require __DIR__ . '/db.php';
$id = (int) ($_POST['id'] ?? $_GET['id'] ?? 0);
$nom = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $nom = trim($_POST['nom'] ?? '');
    if ($nom !== '') {
        if ($id) {
            $pdo->prepare('UPDATE categories SET nom = ? WHERE id = ?')->execute([$nom, $id]);
        } else {
            $pdo->prepare('INSERT INTO categories (nom) VALUES (?)')->execute([$nom]);
        }
        header('Location: index.php');
        exit;
    }
} elseif ($id) {
    $req = $pdo->prepare('SELECT nom FROM categories WHERE id = ?');
    $req->execute([$id]);
    $nom = $req->fetchColumn();
}
?>
<h1><?= $id ? 'Modifier' : 'Ajouter' ?> une catégorie</h1>
<form method="post">
  <input type="hidden" name="id" value="<?= $id ?>">
  <input name="nom" value="<?= htmlspecialchars($nom) ?>">
  <button>Enregistrer</button>
</form>

Exercice 2 · Mettre à jour le stock

Sur la fiche d'un produit, un petit formulaire « Réceptionner » ajoute une quantité au stock (UPDATE ... SET stock = stock + ?). Refusez une quantité négative ou nulle.

Voir le corrigé
<?php
require __DIR__ . '/db.php';
$id = (int) ($_POST['id'] ?? 0);
$qte = (int) ($_POST['qte'] ?? 0);
if ($qte <= 0) {
    exit('La quantité doit être positive.');
}
$req = $pdo->prepare('UPDATE produits SET stock = stock + :qte WHERE id = :id');
$req->execute(['qte' => $qte, 'id' => $id]);
if ($req->rowCount() === 0) {
    exit('Produit introuvable.');
}
header("Location: produit.php?id=$id");
exit;

Exercice 3 · Pourquoi POST pour supprimer ?

Un collègue propose un simple lien <a href="supprimer.php?id=4">Supprimer</a>. Expliquez en trois points pourquoi c'est une mauvaise idée.

Voir le corrigé
1. Un GET doit seulement lire : les navigateurs, les robots d'indexation et certains antivirus suivent les liens tout seuls, et pourraient tout supprimer.
2. Un lien peut être déclenché depuis un autre site (une image <img src="...supprimer.php?id=4">) sans que l'administrateur s'en rende compte (attaque CSRF, leçon C.5).
3. Un POST passe par un formulaire, qu'on peut protéger par un jeton et faire précéder d'une confirmation.

5Vérifier

1. Quelle requête correspond au U de CRUD ?
2. Pourquoi rediriger avec header('Location: ...') après un INSERT réussi ?
3. Que se passe-t-il avec « DELETE FROM categories » sans WHERE ?