Pour rappel, MySQL est un SGBD (Système de Gestion de Bases de Données) qui est très souvent associé à PHP. Il faut connaître la syntaxe objet de php pour comprendre PDO.

Extension PDO 

L'extension PDO (PHP Data Objects)  est un outil qui permet d'accéder à n'importe quel SGBD. Il est très populaire et c'est avec lui que nous allons apprendre à établir la communication entre PHP et MySQL. 

Normalement, PDO est activé par défaut. Pour le vérifier, on peut afficher une page php qui renvoie phpinfo() :

<?php
phpinfo();

Vous devriez alors trouver les informations suivantes :

PDO support enabled
PDO drivers mysql

Si vous avez besoin de l'activer, ouvrez le fichier de configuration de PHP php.ini et décommentez la ligne suivante :

extension=php_pdo_mysql.dll

Connexion

Pour se connecter à une base de données MySQL via du PHP et son extension PDO, il faut créer une nouvelle instance de PDO. Il vous faudra pour cela fournir 3 arguments :

  1. le premier argument est un peu complexe puisqu'il comprend 3 informations :
    1. l'adresse de la machine "host" qui héberge Mysql
    2. le nom de la base de données
    3. le type d'encodage
  2. le deuxième argument permet de spécifier le nom de l'utilisateur de la base de données
  3. le troisième argument est le mot de passe de l'utilisateur de la base de données

Par exemple :

$pdo = new PDO('mysql:host=localhost;dbname=mycms;charset=utf8', 'bob', 'xxx');

En fait pour que votre code soit plus propre et donne une indication plus lisible à l'utilisateur, on va "catcher" les éventuelles erreurs :

<?php
try {
    $pdo = new PDO('mysql:host=localhost;dbname=mycms;charset=utf8', 'bob', 'xxx');
    $pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
}
catch(PDOException $e) {
    echo "Pb de connexion à la base de données ", $e->getMessage();
}

Requête

L'exécution et la restitution d'une requête peut s'opèrer en 3 étapes :

  1. la création de chaine de caractères de requête
  2. l'exécution de la requête
  3. le parcours et l'affichage des résultats de la requête

Ex de code :

$sql = 'select * from node;';
$req = $pdo->query($sql);

// fetch renvoie les enregistrements un par un
// tant qu'il (while) y a un enregistrement, on reste dans la boucle
while($record = $req->fetch(PDO::FETCH_ASSOC)) {
    // $record est un tableau associatif (FETCH_ASSOC) - Ex $record["nid"];
    // il permet d'accéder à la valeur des champs (colonne) 
    echo $record["nid"];
    echo $record["title"];
}

L'argument "PDO::FETCH_ASSOC"  de la méthode fetch qui permet de récupérer les résultats sous formes de tableau associatifd'objets. L'alternative la plus fréquement utilisée est  "PDO::FETCH_OBJ"" qui vous permettra de récupérer les données sous la forme d'objets.

Gestion des erreurs

Par défaut, PDO est en mode "silence", ce qui veut dire qu'il ne vous préviendra pas forcément dès qu'il aura identifié une erreur.

C'est pour cette raison qu'il est conseillé de passer en mode "WARNING" comme nous l'avons fait précédemment dans notre "catch"

$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

Cela va ensuite nous permettre de mieux gérer les erreurs :

$sql = 'select * from node;';
try {
    $req = $pdo->query($sql);
    while($record = $req->fetch(PDO::FETCH_ASSOC)) {
        print_r($record);
    }
}
catch(PDOException $e) {
    echo "Pb de requête", $e->getMessage();
}

Requêtes préparées

La notions de requête préparée est essentielle dans la gestion d'une base de données car :

  • La requête n'est préparée qu'une seule fois, mais peut être exécutée plusieurs fois avec des paramètres modifiables. Lorsque la requête est préparée, la base de données va analyser, compiler et optimiser son plan pour exécuter la requête. Pour les requêtes complexes, ce processus peut prendre assez de temps, ce qui peut ralentir vos applications si vous devez répéter la même requête plusieurs fois avec différents paramètres. En utilisant les requêtes préparées, vous évitez ainsi de répéter le cycle analyse/compilation/optimisation. Pour résumer, les requêtes préparées utilisent moins de ressources et s'exécutent plus rapidement.
  • Les requêtes préparées empêchent les injection SQL qui sont l'une des failles de sécurité les plus courantes.
  • Les paramètres pour préparer les requêtes n'ont pas besoin d'être entre guillemets, c'est automatiquement géré.

Selection avec une requête préparée

try {
    $data = [
        'nid' => $node_id
    ];
    $req = self::$pdo->prepare('SELECT * FROM node WHERE nid = :nid');
    $req->execute($data);
    return $req->fetch(PDO::FETCH_OBJ);
} catch (PDOException $e) {
    echo "Pb de requête", $e->getMessage();
}

Update avec une requête préparée

try {
    $data = [
        'nid' => $_POST['nid'],
        'title' => $_POST['title'],
        'seo_title' => $_POST['seo_title'],
        'body' => $_POST['body'],
        'path' => $_POST['path'],
    ];

    $req = self::$pdo->prepare('UPDATE node SET 
        title = :title, seo_title = :seo_title, body = :body, path = :path   
        WHERE nid = :nid');
    $req->execute($data);

} catch (PDOException $e) {
    echo "Pb de requête", $e->getMessage();
}

Insertion avec une requête préparée

try {
    $data = [
        'type' => 'article',
        'title' => 'Deuxième article',
        'body' => '<p>Ceci est le corps de mon deuxième article</p>',
        'path' => '/deuxieme-article'
    ];
    $req = $pdo->prepare('INSERT INTO node (type,title,body,path) VALUES (:type,:title,:body,:path)');
    $req->execute($data);
}
catch(PDOException $e) {
    echo "Pb de requête", $e->getMessage();
}

Suppression avec une requête préparée

try {
    $data = [
      'nid' => $nid
    ];
    // Requête préparée
    $req = $pdo->prepare('DELETE FROM node WHERE nid = :nid');
    
    //Execution de la requête
    $req->execute($data);
catch(PDOException $e) { echo "Pb de requête", $e->getMessage(); }

Exercice :

Créez via phpmyadmin votre base de données "mycms" et utilisez ce code sql pour créer la table "node" avec quelques enregistrements.

  • Créer une première page qui liste les nodes enregistrés en base de données en affichant uniquement : l'id, le titre et un lien "modifier". Exemple :
    tableau edit nodes
  • au click sur le bouton modifier, un formulaire prérempli avec toutes les informations (sauf le nid)  du "node" en question va permettre à l'internaute de modifier les différents champs.
  • A la validation de ce formulaire, la listes des "nodes" sera à nouveau affichée (seulement id, titre et lien "modifier").