8828 sujets

Développement web côté serveur, CMS

Bonjour à tous
Je suis tombé sur le problème suivant:
J'ai une table Members dans laquelle je référence les membres de l'association
J'ai une table MemberGroups dans laquelle sont indiqués les groupes auxquels un membre appartient,
par exemple un membre peut être dans le groupe "actif" et dans le groupe "membre du CA".
Quand j'essaie de créer un membre puis de lui affecter un ou plusieurs groupes (par deux requêtes successives), tout se passe comme si la création du membre n'avait pas encore eu lieu au moment où je l'affecte à un groupe: le serveur MySQL répond qu'il y a une erreur dans les contraintes.
J'ai également d'autres cas moins nets qui me laissent penser que deux requêtes successives ne se déroulent pas exactement dans l'ordre où elles sont demandées, ou bien que les tables de contraintes ne sont pas immédiatement mises à jour.
Je n'ai rien trouvé sur ce sujet dans la documentation.
Quelqu'un pourrait il éclairer ma lanterne ?
Modérateur
Salut,

En reprenant cette modélisation (le MPD), tu dois faire en sorte que tes tables soient en innoDB et qu'elles aient cet aspect.


CREATE TABLE IF NOT EXISTS members (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    firstname VARCHAR(32) DEFAULT '',
    lastname VARCHAR(32) NOT NULL
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS groups (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(32) NOT NULL
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS groups_members (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    members_id INT NOT NULL,
    groups_id INT NOT NULL,

    CONSTRAINT fk_gm_member FOREIGN KEY (members_id) REFERENCES members(id) ON UPDATE CASCADE ON DELETE CASCADE,
    CONSTRAINT fk_gm_group FOREIGN KEY (groups_id) REFERENCES groups(id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB;


Comme tes tables sont déjà créées, tu peux vérifier avec cette commande :

SHOW TABLE STATUS WHERE Name IN ('members', 'groups', 'groups_members');


Si une table n'utilise pas le bon moteur, je t'invite à faire un alter table. exemple :

ALTER TABLE le_nom_de_ta_table ENGINE=InnoDB;


Puisque tu développes en php, tu dois utiliser ceinture et bretelles pour ce genre de manipulation (try/catch et les transaction (d'où innoDB)). Pourquoi ? Parce que tu enchaînes plusieurs requêtes dépendantes !


<?php
try {
    // 1. Démarrer la transaction
    $pdo->beginTransaction();

    // 2. Insérer le nouveau membre
    $stmtMember = $pdo->prepare("
        INSERT INTO members (firstname, lastname) 
        VALUES (:firstname, :lastname)
    ");
    $stmtMember->execute([
        ':firstname' => 'Jean',
        ':lastname'  => 'Dupont'
    ]);

    // 3. Récupérer l'ID généré par l'AUTO_INCREMENT
    $memberId = $pdo->lastInsertId();

    // 4. Associer le membre à un ou plusieurs groupes
    $groupIds = [1, 2]; // Ex: "Actif" (1) et "Membre du CA" (2)

    $stmtGroup = $pdo->prepare("
        INSERT INTO groups_members (members_id, groups_id) 
        VALUES (:member_id, :group_id)
    ");

    foreach ($groupIds as $groupId) {
        $stmtGroup->execute([
            ':member_id' => $memberId,
            ':group_id'  => $groupId
        ]);
    }

    // 5. Valider définitivement les requêtes
    $pdo->commit();
    echo "Membre créé avec succès (ID : $memberId) et associé à ses groupes !";

} catch (PDOException $e) {
    // En cas d'erreur (ex: le groupe n'existe pas), annuler toutes les opérations
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    echo "Erreur lors de la création : " . $e->getMessage();
}


ps : À noter que depuis MySQL 5.5 (sorti il y a plus de 10 ans), InnoDB est le moteur par défaut. Si tu n'as rien spécifié à la création initiale de tes tables, elles sont très probablement déjà en InnoDB.
Modifié par Niuxe (25 Aug 2026 - 18:40)