Aperçu des sections

  • Voici ce qu'il faut maîtriser un minimum pour bien commencer ce cours :

    • les bases de PHP
    • super globales PHP
    • les bases de données
    • SQL

    Important

    PDO étant une classe, vous êtes censé être au minimum "initié" à la POO. En revanche, on peut découvrir PDO sans forcément avoir vu la POO, donc si vous ne comprenez pas toute la partie "objet" de PDO ça n'est pas grave, mais il vous faudra rapidement approfondir la POO afin de mieux cerner PDO.


  • Présentation

    Depuis PHP5, PDO (pour PHP Data Object) est devenu la méthode de travail standardisée de PHP pour travailler avec les bases de données. Auparavant, PHP offrait simplement des fonctions natives permettant de travailler facilement avec MySQL (tel que mysql_query()), ou bien quelques autres SGBDR. Bien que fonctionnelles et pratiques, ces fonctions offraient assez peu de souplesse et de sécurité. Il se peut que vous en croisiez encore sur des vieux projets, mais la norme aujourd'hui c'est bien PDO.

    PDO est un ensemble de classes PHP, spécialisées dans l'interface avec les bases de données. C'est une couche d'abstraction qui vous permet de travailler à peu près de la même manière avec tous les types de bases de données (MySQL, MariaDB, SQLite, etc...). Cela veux dire que la migration d'un SGBDR vers un autre sera simplifiée, et que vous pouvez travailler avec des bases de données de différents types en parallèle, sans trop de problèmes.

    De plus, PDO vous offre tout un panel d'options et de paramètres qui vous permettent de mieux travailler avec les bases de données, contrairement aux anciennes fonctions natives de PHP, assez limitées.

  • Les trois classes de PDO

    PDO est organisé autour de trois classes qui remplissent chacun un rôle bien distinct :

    1. la classe PDO : c'est la classe qui permet la connexion avec le système de base de données (gestion des drivers, authentification, etc...)
    2. la classe PDOStatement : c'est la classe qui va vous permettent d'échanger des données avec la base de données (exécuter et exploiter des requêtes)
    3. la classe PDOException : c'est la classe qui va vous permettre de gérer les erreurs PDO rencontrées lors de l'exécution de vos script


    Statement et Exceptions sont appelées automatiquement lorsque vous instanciez un nouvel objet PDO pour une connexion à la base de données.

  • Se connecter à une base de données

    Lorsque vous travaillez avec une base de données, vous utilisez un logiciel "extérieur" à PHP (le serveur de base de données). Il va donc falloir que PHP se connecte au serveur de base de données pour pouvoir échanger des informations avec celui-ci. PDO contient tous les éléments nécessaires à cela, et il dispose de drivers adaptés. Les drivers sont des logiciels bas niveau, qui permettent à PHP de communiquer avec les différents systèmes de base de données (MySQL, etc...). Ils sont tous différents, donc il faut des drivers différents en fonction du SGBDR utilisé.


    PDO étant une classe, c'est via l'instanciation d'un nouvel objet PDO que l'on va se connecter à la base de données. Le constructeur de PDO prends plusieurs paramètres, qui correspondent aux données d'identification à la base de données. 

    Généralement, on aura donc :

    • un nom d'hôte (localhost, ou tout autre nom d'hôte)
    • le nom de la base de données
    • le nom de l'utilisateur qui s'y connecte (root, mais normalement c'est un autre utilisateur si on fait bien les choses)
    • le mot de passe de cet utilisateur


    Exemple :

    $db = new PDO("mysql:host=localhost; dbname=mabasededonnees;", 'julien', '1234');


    Dans cet exemple, on instancie un nouvel objet PDO dans une variable $db. Ce sera via cette variable que vous lancerez vos requêtes SQL par la suite. Cette variable est une instance de la classe PDO, donc vous disposerez de toutes les méthodes de PDO via l'objet instancié. Attention : dans cet exemple on se connecte à une base de données MySQL. Si votre base de données est différente, il faudra alors charger des drivers différents (ex : postgresql => pgsql).

    Voici quelques bonnes pratiques pour la connexion à la base de données :

    • mettre la connexion dans un try/catch afin de bien détecter et gérer une potentielle erreur. L'accès à la bdd étant vital pour votre programme, vous ne pouvez pas continuer à exécuter un script si la connexion ne s'est pas bien passée
    • créer un fichier dédié à la connexion bdd, afin de ne pas se répéter dans toutes les pages qui ont besoin de PDO (beaucoup en général). Vous appellerez alors ce fichier dans les pages concernées avec un simple require_once() par la suite


    Exemple d'un fichier de connexion standard, nommé db-connect.inc.php :

    try {
      $db = new PDO("mysql:host=$host_name; dbname=$database;", $user_name, $password);
    } catch (PDOException $e) {
      echo "Erreur!: " . $e->getMessage() . "<br/>";
      die();
    }

    Vous pourrez rajouter d'autres choses à votre guise dans ce fichier (ex : fonction de debug, fonctions utilitaires, données d'authentification, etc...), mais essayez de ne mettre que des choses en lien direct avec la base de données ou PDO afin de ne pas tout mélanger.


    Les options de PDO

    Il y a un dernier paramètre possible dans le constructeur, ce sont les options que vous pouvez rajouter à la configuration de PDO. Elles permettent de modifier la gestion des erreurs, changer des comportements par défaut, etc... Vous pouvez les passer en tableau via le paramètre "option" du constructeur, ou bien utiliser une méthode dédiée de la classe PDO : setAttribute(). Voici un lien vers les différentes options de configuration de PDO. La modification de ces attributs peut être utile dans certains cas, mais PDO marche très bien avec un comportement par défaut.


    Pour une documentation plus précise, je vous invite à jeter un œil à la documentation officielle du constructeur PDO.

  • Exécuter une requête SQL

    Voici les deux méthodes standards qui permettent d'exécuter une requête SQL. Par "exécuter", on entend le fait de l'envoyer au serveur de base de données sur lequel PHP est connecté, et d'attendre une réponse de celui-ci.

    Méthodes d'exécution d'une requête SQL non-préparée :


    • query() : vous permet d'exécuter un SELECT, et vous retournera l'ensemble des résultats qui correspondent à votre requête
    • exec() : est faites pour les UPDATE / INSERT / DELETE. Elle ne retourne pas de jeu de données, en revanche elle vous retourne le nombre de lignes affectées par la requête qui vient d'être exécutée


    Exemple avec la méthode query() :

    $query = $db->query("SELECT pseudo FROM utilisateur");   /* Retournera la liste des pseudos de tous les utilisateurs */


    Exemple avec la méthode exec() :

    $result = $db->exec("DELETE FROM utilisateur WHERE id = 3");  /*Supprimera l'utilisateur n°3, et retournera 1 (une ligne supprimée)*/


    Attention : ces méthodes ne passant pas par la phase de préparation, il faut être bien sûr que les paramètres envoyés dans la chaîne de caractères ne sont pas sensibles, et surtout ne viennent pas d'une saisie utilisateur.

  • quote() et injections SQL

    Quand vous recevez des informations saisies par l'utilisateur, vous ne savez pas trop ce que la personne a pu saisir comme données. Afin de protéger votre système d'une injection SQL, ou de potentiels caractères invalides (ex : des guillemets), vous pouvez appliquer la méthode quote() à vos futures données. Cette méthode aura pour effet d'échapper tous les caractères potentiellement risqués lors de l'exécution de la requête dans le SGBDR, tels que les guillemets, apostrophes, point-virgules, etc... Ces caractères pourraient "couper" votre requête de manière archaïque, et faire, au mieux, planter votre requête, au pire, exécuter du code SQL envoyé par le client. 



    Exemple d'injection SQL


    Si j'envoie cette requête :

    http://formation.webboy.fr/php/pdo/sandbox.php?test=ok;DELETE%20FROM%20test;   /* DELETE FROM test */


    À ce code : 

    require_once "db-connect.inc.php";
    $test = $_GET['test']; /* Sans quote() :( */
    $testQuote = $db->quote($_GET['test']); /* avec quote() :) */
    echo $test;
    echo "<br />";
    echo $testQuote;


    Cela me renverra :

    ok;DELETE FROM test;   /* Ici, nous avons une deuxième requête SQL (non-désirée) à cause du point virgule. Ceci s'appel une injection SQL. */
    'ok;DELETE FROM test;' /*Ici, la valeur reçue est bien traitée comme une chaîne, même si celle-ci contient point virgule */


    Examinons les deux cas de figure :

    1. si j'envoie la première ligne comme paramètre dans une requête SQL, ma requête sera coupée par le point virgule, est la partie DELETE FROM test sera exécutée comme une seconde requête SQL valide. Résultat : ma table "test" sera totalement vidée...  Oups ?
    2. la deuxième requête étant entourées par des guillemets, le SGBDR prendra tout ça comme une seule et même valeur, et la traitera sans couper la requête initiale à cause du point virgule. Yeah !


    La méthode quote() est vraiment la méthode de base pour protéger les variables contenues dans une requête SQL. Il faut absolument l'utiliser si vous faites des requêtes très peu préparées qui contiennent des données provenant directement d'une saisie utilisateur. D'autres méthodes de préparation des requêtes sécurisent automatiquement les variables contenues dans une requête.
  • Les requêtes préparées

    La méthode prepare() de l'objet PDO vous permet de définir une requête, mais sans lui donner ses valeurs finales. Vous allez pouvoir déterminer les paramètres différenciant (ex : id = 2 / id = 3 / etc...) en leur donnant une clé qui sera remplacée par la vraie valeur plus tard, lors de l'exécution. La méthode prepare() peut rendre vos requêtes plus optimisées, notamment via la gestion d'un cache pour les requêtes exécutées plusieurs fois. Aussi, le remplacement des clés par les valeurs finales sera automatiquement échappé, ce qui améliore grandement la sécurité, et vous évite d'utiliser la méthode quote() partout.





    Valeurs avec paramètres nommés

    Nous allons réaliser une requête qui va recherche un utilisateur par son id, son nom d'utilisateur et son e-mail.

    Exemple de paramètres :

    • :id
    • :user
    • :email


    Ce qui pourrait donner une requête dans ce style :

    $query = $db->prepare("SELECT * FROM utilisateur WHERE id = :id AND user = :user AND email = :email");
    
    $query->execute(array( ':id' => $_GET['id'], ':user' => $_GET['user'], ':email' => $_GET['email'] ));
    Dans cet exemple, les termes :id, :user et :email seront remplacés par les bonnes valeurs lors de l'exécution de la requête, via un tableau envoyé à la méthode execute().



    Valeurs par marqueurs

    Cette approche permet de ne pas nommer distinctement vos paramètres (comme :id ou :user), mais de leur donner juste une existence via un point d'interrogation ?. Chaque paramètre pourra alors être défini selon l'ordre et le nombre de ? qu'il y a dans votre requête.

    Exemple :

    $query = $db->prepare("SELECT * FROM utilisateur WHERE id = ? AND user = ? AND email = ?");
    $query->execute(array($_GET['id'], $_GET['user'], $_GET['email'])); /* L'ordre est important, comme les paramètres d'une fonction */
    Bien que plus rapide à écrire, je vous déconseille cette approche. Car si vous changer votre requête SQL, il vous faudra alors penser à changer aussi l'ordre de vos paramètres dans l'exécution de votre requête. Et sur des grosses requêtes, cela peut vite devenir fastidieux.
  • Lier des variables dans une requête

    On peut aussi assigner des valeurs à des paramètres de requête SQL en utilisant les méthodes bindParam() ou bindValue(). Ces méthodes vous permettent de binder (lier) des variables avec des paramètres avant d'exécuter la requête. Cela peut être utile dans le cas ou beaucoup de code doit être exécuté entre la préparation de la requête et son exécution. Si les valeurs de vos paramètres peuvent changer plusieurs fois avant l'exécution finale de la requête, alors ces méthodes peuvent être plus adaptées que celles vues plus haut dans le cours.


    Exemple : lister des utilisateurs par type

    $type = '';
    $query = $db->prepare('SELECT * FROM utilisateurs WHERE type = :type');
    $query->bindParam(':type', $type);
    /*
    ...Du code qui va permettre de définir le type d'utilisateur demandé...
    
    admin = a
    contributeur = c
    modérateur = m
    abonné = b
    visiteur = v
    ....
    
    $type = a ou c ou m ou b ou v...
    */
    $query->execute();


    Certains paramètres permettant d'affiner l'utilisation de la méthode sont possibles, tel que le type ou la taille de la variable à lier.


    La principale différence entre bindParam() et bindValue(), c'est que bindParam() va lier un paramètre avec une référence de variable, alors que bindValue() va lier un paramètre avec une valeur de variable. Cela veut dire qu'avec bindValue(), si la variable change de valeur, la valeur dans la requête ne changera pas. En revanche, avec bindParam(), la valeur du paramètre prendra en compte la valeur courante de la variable lors de l'exécution, même si celle-ci a changée entre temps.

    Si vous ne connaissez pas la notion de référence en PHP, veuillez lire la doc officielle sur le sujet.
    Voici un lien sur stackoverflow illustrant bien la différence entre bindParam() et bindValue() : https://stackoverflow.com/questions/1179874/what-is-the-difference-between-bindparam-and-bindvalue
  • Exploiter les résultats d'une requête

    Lorsqu'une requête est exécutée via PDO, PHP envoi la chaîne de caractère au SGBDR. Le SGBDR la traite, il va lire ou modifier les données contenues dans la base de données, puis va renvoyer une réponse à PHP. 


    Cette réponse peut être de différente nature :

    • un jeu de données, suite à un SELECT
    • un nombre représentant la quantité de lignes affectées par une requête (lors d'un INSERT / UPDATE / DELETE par exemple)
    • une erreur


    Nous allons voir ici comment récupérer puis traiter les réponses valides (donc sans erreur) du SGBDR. Cette étape est cruciale, car on va transformer les données reçues par le SGBDR en variables exploitables en PHP dans votre script ! Fini les tableaux associatifs pour s'entraîner : on passe aux choses sérieuses.
  • La méthode fetch()

    La méthode fetch() est la plus simple de toute. Elle vous renvoie le premier enregistrement d'un jeu de résultat contenu dans la réponse de la bdd. 

    Vous pouvez l'utiliser dans de deux manières :

    • soit vous n'attendez qu'une seule ligne de réponse (ex : "SELECT * FROM utilisateurs WHERE id = 35").  Dans ce cas, la variable dans laquelle vous assignerez le fetch() contiendra simplement vos informations.
    • soit vous attendez plusieurs résultats possibles (ex : "SELECT * FROM utilisateurs WHERE type='a'"). Dans ce cas, il faudra boucler plusieurs fois sur votre fetch (cqfd : l'exécuter plusieurs fois) pour exploiter chaque ligne les unes après les autres.


    On utilise rarement fetch() sans déterminer son paramètre principal : le "fetch style". Ce paramètre va vous permettre de demander un formatage spécial des données reçues. Par défaut, PDO vous renvoie des données au format PDO::FETCH_BOTH. Vous verrez qu'elles ne sont pas très exploitables en l'état, car votre tableau de réponses contiendra le nom des colonnes au même niveau que les valeurs reçues. 

    Voici un exemple :

    $query = $db->prepare("SELECT * FROM user WHERE pseudo = :user AND password = :password");
    $query->execute(array(
      ':user' => 'julien',
      ':password' => 123
    ));
    $result = $query->fetch();
    debug($result);


    Ce code affichera :

    Array
    (
        [id] => 1
        [0] => 1
        [pseudo] => julien
        [1] => julien
        [password] => 123
        [2] => 123
    )
    Ce type de retour n'est pas aisé à manipuler car il ne reflète pas très bien les lignes et colonnes (clés/valeurs) correspondant à la base de données.

    On va donc pouvoir changer le style de formatage de la réponse suivant nos préférences, et les besoins de l'application.


    Exemple avec PDO::FETCH_ASSOC (même code que l'exemple précédent) :

    $result = $query->fetch(PDO::FETCH_ASSOC);  /* Le style de formatage peut être envoyé en premier paramètre de la méthode fetch() */

    Affichera :

    Array
    (
        [id] => 1
        [pseudo] => julien
        [password] => 123
    )
    Ces données sont beaucoup plus cohérentes que l'exemple précédent. En revanche on obtient un simple tableau associatif clé/valeur. Voici un autre exemple si vous souhaitez récupérer des données sous forme d'objets.


    Exemple avec PDO::FETCH_OBJ :

    $result = $query->fetch(PDO::FETCH_OBJ);  /* FETCH_OBJ retournera les résultats sous forme d'objet "standard" stdClass de php */

    Affichera :

    stdClass Object

      [id] => 1 
      [pseudo] => julien 
      [password] => 123 
    )



    À cette étape, vous n'aurez plus qu'à traiter votre variable $result comme n'importe quel autre variable PHP :

    Par exemple :


    echo $result['pseudo']   /* Version tableau associatif FETCH_ASSOC */
    echo $result->pseudo   /* Version objet standard FETCH_OBJ */

    Donc pour résumé, bien qu'étant un paramètre optionnel, le fetch_style va grandement influer sur la manière dont vous aurez accès à vos données dans votre script. Donc il faut bien le traiter ! Vous pouvez changer la valeur du paramètre par défaut dans la configuration de PDO.

    C'est important le style !

    Voici un lien vers les différents types de barbes la méthode fetch() de PDO dans la documentation officielle.
    Note : vous pouvez aussi déterminer le fetch_mode par défaut en utilisant la méthode setAttribute() de PDO. Ce qui permet de ne pas avoir à le spécifier à chaque fetch(). Pratique.


    Pour finir sur la méthode fetch(), voici comment on pourrait traiter une réponse de requête qui renvoi plusieurs lignes grâce à un fetch() et un boucle :

    while ($row = $query->fetch(PDO::FETCH_ASSOC)) {  /*Tant qu'il reste des lignes... ...après, fetch renvoi false donc on sort de la boucle */
        print_r($row); /* Ici, $row représente une des lignes du retour de la requête SQL */
    }

    Dans ce type d'utilisation, chaque ligne de résultat sera itérée comme un tableau classique. La méthode fetch() va déplacer le curseur de la ligne en cours à chaque itération (comme un index $i : 0, 1, 2, 3, 4,...), et la variable $row recevra alors les données de la ligne suivante (ici, sous forme de tableau associatif grâce à PDO::FETCH_ASSOC). Quand il n'y a plus de lignes, fetch() renvoie false, et on sort donc de la boucle.

    Bien que fonctionnelle, et pouvant s'avérer plus adaptée dans certains cas, on préférera la méthode fecthAll() plutôt que fetch() pour traiter des jeux de données contenant plusieurs lignes.
  • La méthode fetchAll()

    La méthode fetchAll() fonctionne à peu près de la même manière que fetch(), sauf qu'elle va vous renvoyer directement un tableau PHP contenant toutes les lignes de la réponse. Donc si vous avez plusieurs lignes à récupérer, vous n'aurez pas besoin d'itérer sur la méthode fetch() afin de parcourir les lignes une à une. Vous récupèrerez juste le résultat de fetchAll() dans une variable, que vous pourrez facilement parcourir comme un tableau classique.


    Exemple sur une messagerie :

    $query = $db->query("SELECT * FROM messages WHERE user_id = 23");
    $messages = $query->fetchAll(PDO::FETCH_OBJ);
    foreach($messages as $k => $message){  echo $message->content; /* ...du code exploitant un tableau d'objets contenant les messages de l'utilisateur n°23 */
    }


    Simple non ? Comme d'habitude, il y a quelque paramètres qui permettent de modifier le comportement de cette fonction, et qui peuvent vous permettre d'adapter le résultat à vos besoins. 

    En voici un pour l'exemple :
    • PDO::FETCH_CLASS : ce paramètre "fetch_style" vous permet d'instancier un objet à partir d'une classe existante dans votre programme en l'hydratant directement avec les données reçues de la requête. Si votre programme est bien conçu, et que vous exploitez bien la POO, cela peut s'avérer très pratique.
    Résumé : la méthode fetch() vous permet de récupérer vos lignes une par une, tandis que la méthode fetchAll() récupère tout d'un coup.


    ----------

    A voir en plus :

    fetchColumn

    fetchobject

    bindcolumn

    ----------

  • Exploiter les résultats des INSERT, DELETE, UPDATE

    Lorsque l'on exécute des requêtes de type INSERT, UPDATE ou DELETE, on ne va pas récupérer de données à proprement parlé. C'est-à-dire que la requête ne génère pas de jeu de données à exploiter.

    Voici quelques exemples :

    • INSERT : la bdd va ajouter une ligne dans une table, mais ne va pas vous retourner les données correspondantes
    • UPDATE : la bdd va modifier le contenu d'une ligne déjà existante, mais ne va pas vous retourner les données correspondantes
    • DELETE : la bdd va supprimer une ligne déjà existante, mais ne va pas vous retourner les données correspondantes


    Et c'est totalement normal. Sauf que dans certains cas, on aimerait bien avoir un retour un peu plus explicite que le simple code SQL disant que "tout s'est bien passé". Par exemple, il arrive très souvent que lorsque l'on créé un utilisateur dans notre programme, on souhaite connaître l'id de l’utilisateur nouvellement créé. Ou bien quand on supprime un ensemble de ligne, on aimerait bien connaître le nombre de lignes affectées par la requête. Voici les méthodes qui permettent de faire cela.


    lastInsertId()

    Permet de récupérer l'id de la dernière requête SQL INSERT exécutée.

    Exemple :

    $userId = 24;
    $title = "Titre message";
    $text = "Texte message";
    $query = $db->prepare("INSERT INTO message (user_id, title, text) VALUES ($userId, :title, :text)"); /* Insertion d'un nouveau message dans la table message. Note : $userId n'est pas une saisie utilisateur, donc c'est bon */
    $query->execute(array(
      ':title' => $title,
      ':text' => $text
    ));
    $messageId = $db->lastInsertId(); /* Récupération de l'id du message nouvellement créé */
    $query = $db->query("INSERT INTO message_lu (user_id, message_id, lu) VALUES ($userId, $messageId, false)"); /* Le message n'a pas encore été lu */

    => Pratique


    rowCount()

    Retourne le nombre de lignes affectées par le dernier appel à la méthode execute().

    Exemple :

    /*Supprime tous les messages d'un utilisateur*/
    $query = $db->prepare("DELETE FROM message WHERE user_id = $userId");
    $query->execute();
    $deletedMessage = $query->rowCount(); /*On récupère le nombre de lignes affectées par la dernière requête exécutée */
    if ($query === false) { /* Gestion de l'erreur si problème */
      pdo_error($query); /* fonction "maison" */
    } else {
      /*Affichera une information à l'utilisateur contenant le nombre de messages supprimés*/
      header("Location: dashboard.php?info=messageDeleted&messageDeletedCount={$deletedMessage}");
    }
  • Débugger avec PDO

    PDO offre des méthodes permettant de débugger facilement une requête qui aurait rencontrée un problème. Si par exemple vous avez fait une erreur de syntaxe dans votre requête, il sera impossible de l'exécuter dans votre SGBDR, et celui-ci renverra une erreur (avec un code erreur) vous permettant de cibler facilement la nature du problème. PDO peut récupérer ces erreurs émises par le SGBDR, et vous les présenter correctement via des méthodes adaptées. 

    Voici les deux méthodes principales :


    • errorInfo() : renvoi un tableau contenant des informations sur l'erreur survenue lors de la dernière opération exécutée. Le champ 0 correspond au code erreur SQL (très pratique), et le champ 2 renvoie le message texte littéral (très pratique aussi). En exploitant bien cette méthode, vous détecterez très rapidement votre bug grâce aux informations détaillées que contient le tableau
    • errorCode() : retourne seulement le code erreur du SGBDR. Peut-être utile pour gérer de manière programmatique certaines erreurs très précises, moins pour corriger un bug.
    Voici un lien qui vous permet de retrouver la signification des codes erreurs/status de MySQL : https://www.fromdual.com/mysql-error-codes-and-messages


    Il y a aussi la méthode debugDumpParams() qui permet d'afficher le contenu d'une requête préparée avant qu'elle ne soit exécutée. C'est une sorte de var_dump(), mais spécialisé pour PDO. Cette méthode n'affiche pas seulement la requête en elle-même, mais des informations diverses supplémentaires la concernant.

    Premier bug de l'histoire

    Premier bug de l'histoire !


  • Exercices

    Voici quelques exercices pour s'entrainer avec PDO. Ils vont du plus simple au plus compliqué :

    1. annuaire : travail avec une seule table déjà remplie
    2. blogging : travail sur plusieurs tables déjà remplies
    3. système de votation : à vous de concevoir la base de donnée et de l'exploiter

  • Système de transaction : back to the future !


    La gestion des transactions est un concept un peu plus avancé de PDO et des SGBDR. Pour faire simple, cela permet de simuler l'exécution d'un ensemble de requêtes, et de les exécuter seulement si tout s'est passé comme prévu.

    Exemple :

    Si l'on souhaite supprimer toute une série d'informations présentent dans de nombreuses tables du la bdd, la suppression peux parfois être interdite à cause de clé étrangères, ou bien d'une conception particulière. On va donc écrire nos différentes requêtes de DELETE (et parfois même des SELECT ou des UPDATE pour récupérer ou mettre à jour certaines infos), puis les exécuter les unes après les autres. 

    Le problème, c'est que s’il y a eu une erreur lors de l'exécution de toutes ces requêtes, certains champs auront déjà été effacés, et leur données seront perdues sans que l'on soit arrivé au bout du processus de suppression. Cela peut créer un problème d'intégrité de la base de données extrêmement problématique (données perdues + base de données instable).

    Pour remédier à ce problème, on utilisera un système de transaction, qui va permettre de tester le bon fonctionnement de l'ensemble des requêtes, les unes après les autres :

    • si on arrive au bout du test sans encombre, alors on va "engager" les requêtes, et elles seront alors réellement exécutées (commit)
    • si un problème survient, on va alors stopper le processus de test afin de ne pas réellement supprimer les données de manière irréversible, et de ne pas nuire à l'intégrité de la base de données (rollback)
    Pour mettre en place ce système, il vous faudra utiliser les méthodes suivantes :
    1. beginTransaction() : déclarer le début d'une transaction
    2. rollBack() : revenir en arrière
    3. commit() : exécuter les requêtes contenues dans la transaction


    Lien vers la documentation officielle des transactions en PDO

  • Récupérer des données de structure de la DB

    A faire... :


    Exemple :

    SELECT COLUMN_NAME 
    FROM INFORMATION_SCHEMA.COLUMNS