🤩TD 09 et 10 : librairie CRUD en PHP (1/2)

Introduction

  • Dans ces séances consacrées au CRUD (Create Read Update Delete), on va créer une librairie de fonctions PHP. Ces fonctions vont nous permettre d'effectuer les opérations sur les données de la base de données. La librairie de fonctions sera à insérer dans toutes les pages de notre projet SAE203 à l'aide de l'instruction require.

  • Pour se connecter à la base de données, on va utiliser le constructeur de la classe PDO, la fonction PDO() qui prend trois paramètres : une chaîne de caractères contenant les données de connexion (adresse IP de l'hôte, port, nom de la (data)base et charset utilisé), le login et le mot de passe utilisateur.

  • Remarque sur la sécurité :

Tous les fichiers que nous allons créer seront situés dans un sous-dossier de votre site nommé admin/. Ce dossier sera protégé par un fichier .htaccessdans lequel on demandera un login et un mot de passe pour accéder à cette partie privée de votre site. En effet, lorsque votre site sera en ligne, seul un administrateur du site doit avoir le droit de modifier les données de vos tables. Cette partie "sécurité" sera traitée dans une autre séance de la SAE203.

  • Remarque sur le dossier des images :

Toutes les images des albums seront dans la suite de cete séance dans un dossier "images/uploads/" dans notre dossier de base de la SAE203. Ce dossier devra, lorsqu'il sera mis en ligne, pouvoir enregistrer les images téléchargées par les utilisateurs. Il faut donc mettre les DROITS D'ÉCRITURE sur ce dossier sur votre VPS et dans votre dossier de travail (si vous êtes en local sous WAMP/MAMP/LAMP). ATTENTION, les droits d'écriture sont à mettre sur le dossier "uploads" seulement, pas sur le dossier "images", ce qui rendrait modifiables TOUTES les images de votre site. Ici, on ne souhaite que pouvoir écrire les images des albums.

  • Remarque sur le rendu final :

Dans ces deux séances, nous ne traiterons QUE la table 1 de votre SAE203, ce sera à VOUS de FAIRE la même chose pour la gestion de la table 2 dans le rendu final ! Votre code écrit PHP pour la gestion de la table 2 sera aussi évalué dans la note finale !

1. Création de secretxyz123.inc.php :

  • Afin de cacher les informations login et mot de passe dans votre code PHP, on va les mettre dans un fichier spécial qui va définir des chaînes à remplacer par d'autres grâce à la fonction define().

  • Dans le dossier principal de votre SAE203, créez un fichier secretxyz123.inc.php.

  • Dans ce fichier, ajoutez les définitions de votre login et de votre mot de passe utilisateur pour la connexion à votre base de données MySQL :

<?php
  // FICHIER DE DÉFINITION de chaînes de remplacement
	
  // Mettez VOTRE LOGIN ci-dessous (2ème paramètre de define)
  define('LUTILISATEUR', 'mmijlandre');
  // Mettez VOTRE MOT DE PASSE ci-dessous (2ème paramètre de define)
  define('LEMOTDEPASSE', 'toto@1234#');

2. Création de la librairie lib_crud.inc.php :

  • Dans le dossier principal de votre SAE203, créez un fichier lib_crud.inc.php.

  • Dans ce fichier, ajoutez les fonctions de connexion et de déconnexion à la base de données MySQL :

<?php
  // LIBRAIRIE "lib_crud.inc.php"
  // 2022 - BUT MMI - IUT Troyes - URCA
  // JL

  // insertion des dépendances
  require 'secretxyz123.inc.php';

  // connexion à la base de données
  function connexionBD()
  {
    // on initialise la variable de connexion à null
    $mabd = null;
    try {
      // on essaie de se connecter
      // le port et le dbname ci-dessous sont À ADAPTER à vos données
      $mabd = new PDO('mysql:host=127.0.0.1;port=3306;
                dbname=mmijlandre;charset=UTF8;', 
                LUTILISATEUR, LEMOTDEPASSE);
      // on passe le codage en utf-8
      $mabd->query('SET NAMES utf8;');
    } catch (PDOException $e) {
      // s'il y a une erreur, on l'affiche
      echo '<p>Erreur : ' . $e->getMessage() . '</p>';
      die();
    }
    // on retourne la variable de connexion
    return $mabd;
  }

  // déconnexion de la base de données
  function deconnexionBD(&$mabd) {
    // on se déconnexte en mettant la variable de connexion à null 
    $mabd=null;
  }

3. Test de la librairie lib_crud.inc.php :

  • Afin de tester le fonctionnement de la librairie lib_crud.inc.php, modifiez votre code de la page listing.php pour charger la librairie de fonctions et remplacez votre code de connexion et de déconnexion par les fonctions fournies connexionBD() et deconnexionBD().

  • Puis, placez votre code qui réalise l'affichage dans une fonction afficherCatalogue($mabd) dans lib_crud.inc.php.

  • Le début du code de afficherCatalogue($mabd) devrait ressembler à ceci :

    // affichage du catalogue des albums
    function afficherCatalogue($mabd) {
        $req = "SELECT * FROM bandes_dessinees 
                INNER JOIN auteurs 
                ON bandes_dessinees._auteur_id = auteurs.auteur_id";
        try {
            $resultat = $mabd->query($req);
        } catch (PDOException $e) {
            // s'il y a une erreur, on l'affiche
            echo '<p>Erreur : ' . $e->getMessage() . '</p>';
            die();
        }
        // ICI VOTRE CODE POUR AFFICHER LES ALBUMS
        // ...
        // ...
    }
  • Votre code simplifié dans listing.php devrait ressembler à quelque chose comme ça (c'est beaucoup plus court, non ?) :

...
	<body style="font-family:sans-serif;">
		<a href="index.php">Accueil</a> | <a href="listing.php">Catalogue</a> | <a href="admin/admin.php">Admin.</a>
		<hr />
		<h1>Nos albums</h1>
		<hr />
		<?php
		    require 'lib_crud.inc.php';
		    $co=connexionBD();
		    afficherCatalogue($co);
		    deconnexionBD($co);
		?>
	</body>
</html>
  • Le résultat affiché devrait ressembler à quelque chose comme ça (évidemment, cet affichage dépend de vos données et de vos styles CSS) :

4. Création de la page admin.php :

  • Dans votre dossier de travail "sae203", vous devez créer un dossier "admin" (qui sera protégé par un .htaccess plus tard).

  • Dans le menu général, le lien "Admin." va pointer vers "admin/admin.php" (la page d'administration des données de votre site).

  • Dans le dossier admin, on va créer un fichier admin.php dans lequel on va mettre le code :

<!DOCTYPE html>
    <html>
    <head>
        <title>SAE203</title>
    </head>
    <body style="font-family:sans-serif;">
        <a href="../index.php">Accueil</a>
        <hr />
        <h1>Gestion des données</h1>
        <ul>
            <li>Gestion des <a href="table1_gestion.php">albums</a></li>
            <li>Gestion des <a href="table2_gestion.php">auteurs</a></li>
        </ul>
    </body>
</html>
  • Dans le dossier admin, on va créer un fichier table1_gestion.php dans lequel on va mettre le code :

<!DOCTYPE html>
<html>
    <head>
        <title>SAE203</title>
    </head>
    <body>
        <a href="../index.php">Accueil</a>
        <hr />
        <h1>Gestion des données</h1>

        <p><a href="table1_new_form.php">Ajouter une bande dessinée</a></p>
        <?php
            require '../lib_crud.inc.php';
            $co=connexionBD();
            afficherListe($co);
            deconnexionBD($co);
        ?>
    </body>
</html>
  • Il faut donc créer une fonction afficherListe() dans lib_crud.inc.php qui va afficher une table HTML contenant les informations sur les bandes dessinées :

...
    // affichage de la liste des albums pour la gestion
    function afficherListe($mabd) {
        $req = "SELECT * FROM bandes_dessinees 
                INNER JOIN auteurs 
                ON bandes_dessinees._auteur_id = auteurs.auteur_id";
        try {
            $resultat = $mabd->query($req);
        } catch (PDOException $e) {
            // s'il y a une erreur, on l'affiche
            echo '<p>Erreur : ' . $e->getMessage() . '</p>';
            die();
        }
        echo '<table>'."\n";
        echo '<thead><tr><th>Photo</th><th>Titre</th><th>Prix (&euro;)</th><th>Pages</th><th>Auteur</th><th>Modifier</th><th>Supprimer</th></tr></thead>'."\n";
        echo '<tbody>'."\n";
        foreach ($resultat as $value) {
            echo '<tr>'."\n";
            echo '<td><img class="photo" src="../images/uploads/'.$value['bd_photo'].'" alt="image_'.$value['bd_id'].'" /></td>'."\n";
            echo '<td>'.$value['bd_titre'].'</td>'."\n";
            echo '<td>'.$value['bd_prix'].'</td>'."\n";
            echo '<td>'.$value['bd_nb_pages'].'</td>'."\n";
            echo '<td>'.$value['auteur_prenom'].' '.$value['auteur_nom'].'</td>'."\n";
            echo '<td><a href="table1_update_form.php?num='.$value['???'].'">Modifier</a></td>'."\n";
            echo '<td><a href="table1_delete.php?num='.$value['???'].'">Supprimer</a></td>'."\n";
            echo '</tr>'."\n";
        }
        echo '</tbody>'."\n";
        echo '</table>'."\n";
    }
...
  • Attention, dans le code ci-dessus, ... n'est pas une instruction PHP valide, c'est juste pour indiquer que ce code est dans . De plus, il faut changer les ??? pour afficher le numéro de la bande dessinée afin de le passer à la page de modification et à la page de suppression.

  • Testez votre code, la page obtenue decrait ressembler à ceci (selon votre CSS évidemment) :

5. Ajout d'une bande dessinée (liste des auteurs) :

  • Pour ajouter un bande dessinée à notre catalogue (pour insérer les données dans MySQL), on va créer un fichier table1_new_form.php dans lequel on va insérer le code suivant :

<!DOCTYPE html>
<html>
	<head>
	    <title>SAE203</title>
	</head>
	<body style="font-family:sans-serif;">
	    <a href="../index.php">Accueil</a> | <a href="admin.php">Gestion</a>
	    <hr />
	    <h1>Ajouter une bande dessinée</h1>
	    <hr />
	    <form action="table1_new_valide.php" method="POST" enctype="multipart/form-data">
	        Titre : <input type="text" name="titre" required /><br />
	        Année : <input type="number" name="annee" min="-5000" max="3000" required /><br />
	        Nb pages : <input type="number" name="pages" required /><br />
	        Prix : <input type="number" name="prix" min="0.00" max="10000.00" step="0.01" required /><br />
	        Résumé : <textarea name="resume" required></textarea><br />
	        Photo : <input type="file" name="photo" required /><br />
	        Auteur : <select name="auteur" required>
	        <?php
	            require '../lib_crud.inc.php';
	            $co=connexionBD();
	            afficherAuteursOptions($co);
	            deconnexionBD($co);
	        ?>
	        </select><br />
	        <input type="submit" value="Ajouter" />
	    </form>
	</body>
</html>
  • Attention, le formulaire est OBLIGATOIREMENT en méthode POST car on va passer une image à notre site, donc on va utiliser un champ de type file. On précise de plus l'encodage de notre image : multipart/form-data.

  • Pour afficher la liste des auteurs, il faut ajouter dans notre librairie lib_crud.inc.php le code qui va permettre de générer la liste des prénoms et noms des auteurs sous la forme de balises <option> dans une balise HTML <select>.

  • Le code de la fonction afficherAuteursOptions($co) doit ressembler à ceci :

    // afficher les auteurs (prénom et nom) dans des champs "option"
    function afficherAuteursOptions($mabd) {
    	// on sélectionne tous les auteurs de la table auteurs
        $req = "SELECT * FROM auteurs";
        try {
            $resultat = $mabd->query($req);
        } catch (PDOException $e) {
            // s'il y a une erreur, on l'affiche
            echo '<p>Erreur : ' . $e->getMessage() . '</p>';
            die();
        }
        // pour chaque auteur, on met son id, son prénom et son nom 
        // dans une balise <option>
        foreach ($resultat as $value) {
            echo '<option value="'.???.'">'; // id de l'auteur
            echo ???.' '.???; // prénom espace nom
            echo '</option>'."\n";
        }
    }
  • Testez votre code, vous devriez avoir quelque chose comme ceci (la liste déroulante contient bien TOUS les prénoms et noms des auteurs) :

6. Ajout d'une bande dessinée (validation) :

  • On va maintenant valider les changements dans la table bandes_dessinees.

  • On va créer le fichier table1_new_valide.php qui va récupérer les informations de la nouvelle BD (avec l'image à télécharger) et qui va insérer les informations dans la table.

  • Le code de la page table1_new_valide.phpest donné ici :

<!DOCTYPE html>
<html>
	<head>
		<title>SAE203</title>
	</head>
	<body style="font-family:sans-serif;">
	    <a href="../index.php">Accueil</a> | <a href="admin.php">Gestion</a>
	    <hr />
	    <h1>Ajouter une bande dessinée</h1>
	    <hr />
	    <?php
	        require '../lib_crud.inc.php';
	
	        $titre=$_POST['titre'];
	        $prix=$_POST['prix'];
	        $annee=$_POST['annee'];
	        $nbPages=$_POST['pages'];
	        $resume=trim($_POST['resume']);
	        $auteur=$_POST['auteur'];
	        var_dump($_POST);
	        var_dump($_FILES);
	
	        $imageType=$_FILES["photo"]["type"];
	        if ( ($imageType != "image/png") &&
	            ($imageType != "image/jpg") &&
	            ($imageType != "image/jpeg") ) {
	                echo '<p>Désolé, le type d\'image n\'est pas reconnu !';
	                echo 'Seuls les formats PNG et JPEG sont autorisés.</p>'."\n";
	                die();
	        }
	
	        $nouvelleImage = date("Y_m_d_H_i_s")."---".$_FILES["photo"]["name"];
	
	        if(is_uploaded_file($_FILES["photo"]["tmp_name"])) {
	            if(!move_uploaded_file($_FILES["photo"]["tmp_name"], 
	            "../images/uploads/".$nouvelleImage)) {
	                echo '<p>Problème avec la sauvegarde de l\'image, désolé...</p>'."\n";
	                die();
	            }
	        } else {
	            echo '<p>Problème : image non chargée...</p>'."\n";
	            die();
	        }
	
	        $co=connexionBD();
	        ajouterBD($co, $titre, $annee, $prix, 
	        		$nouvelleImage, $nbPages, $resume, $auteur);
	        deconnexionBD($co);
	    ?>
	</body>
</html>
  • Dans ce code, on récupère les informations passées par le formulaire de la page précédente, on vérifie ensuite le type de l'image, on la récupère sur le serveur (VPS ou local) dans le dossier "images/uploads/" (en la renommant en ajoutant la date) et on appelle la fonction ajouterBD() en lui passant les informations nécessaires pour insérer les données dans la table bandes_dessinees.

  • Le code (incomplet) de la fonction ajouterBD() à mettre dans lib_crud.inc.phpest :

    // fonction d'ajout d'une BD dans la table bande_dessinees
    function ajouterBD($mabd, $titre, $annee, $prix, $nouvelleImage, $nbPages, $resume, $auteur)
    {
        $req = 'INSERT INTO bandes_dessinees (bd_titre, bd_annee, bd_prix, bd_photo, bd_nb_pages, bd_resume, _auteur_id) VALUES (???)';
        echo '<p>' . $req . '</p>' . "\n";
        try {
            $resultat = $mabd->query($req);
        } catch (PDOException $e) {
            // s'il y a une erreur, on l'affiche
            echo '<p>Erreur : ' . $e->getMessage() . '</p>';
            die();
        }
        if ($resultat->rowCount() == 1) {
            echo '<p>La bande dessinée ' . $titre . ' a été ajoutée au catalogue.</p>' . "\n";
        } else {
            echo '<p>Erreur lors de l\'ajout.</p>' . "\n";
            die();
        }
    }
  • Il faut remplacer les ??? par le code PHP qui va générer le "INSERT INTO" de façon correcte.

  • Testez votre code jusqu'à avoir la nouvelle bande dessinée qui apparait dans la liste des albums.

7. Un peu de nettoyage :

  • Quand tout fonctionne, vous pouvez "nettoyer" votre code en enlevant TOUS les affichages qui ne servent plus : les requêtes, les print_r(), les var_dump()... Pour cela, mettez-les en commentaires dans tous les fichiers concernés :

//echo '<p>'.$req.'</p>."\n";

//var_dump($_POST);

//var_dump($_FILES);

Dernière mise à jour