M2202 - Algorithmique et PHP David Annebicque 2016 1 TD : Accès aux base de données 1.1 Introduction Une base de données permet de stocker des données de manière durable, contrairement à une session ou un cookie qui ont une durée de vie. Une base de données se compose d une ou plusieurs tables, qui peuvent, ou non, avoir des liens entre-elles. Dans le cadre de la formation MMI nous utilisons une base de données de type MySQL (lire le cours de M2203). Ce TD vise à vous expliquer comment se connecte-t-on à une base de données, comment récupère-t-on des données, comment peut-on ajouter, modifier ou supprimer des données, en d autres termes, comme exécuter les requêtes MySQL grâce au PHP. Il existe plusieurs manière de se connecter à une base de données en PHP. Il y a des méthodes spécifiques en fonction du type de base de données utilisée (mysql ou mysqli par exemple pour une base de données MySQL). Mais il y a aussi des méthodes plus génériques. Nous utiliserons dans le cadre de ce semestre la méthode PDO : PHP Data Object. Cette méthode utilise le concept de programmation orienté objet que vous étudierez durant le semestre 3. Il est donc normal que vous ne compreniez pas précisément la notation ->. Sachez simplement qu elle permet d utiliser des fonctionnalités associées à la connexion à votre base de données. 1.2 Se connecter à une base de données Pour pouvoir se connecter à une base de données, quelque soit la méthode utilisée, vous devez disposer des 4 informations suivantes : User : Login de votre base de données (mmi16xxx) Password : Mot de passe pour accéder à votre base de données (4 caractères en MMI) 1
Serveur : Adresse où se trouve votre base de données (localhost) Nom de la base de données : Le nom de la base de données. (basemmi16xxx) Dans le cadre du DUT MMI le login et le mot de passe de la base de données sont identiques à vos accès pour votre FTP. Le serveur permet de donner l adresse de votre base de données, très souvent, la base de données étant sur le même serveur que votre serveur web, on indique localhost. Dans certain cas, on pourra indiquer une URL ou une adresse IP. 2 $bdd = new PDO('mysql:host=serveur;dbname=nom_de_la_BDD; charset=utf8', 'User', 'Password'); Listing 1: Phrase de connexion à une BDD MySQL Il faut bien sûr remplacer dans l instruction précédente le serveur, le nom de la BDD, le User et le Password par vos informations personnelles. 1.3 PHP: Définition de constantes La connexion à la base de données est potentiellement nécessaire sur beaucoup de fichiers de notre projet. En effet, il faut effectuer la connexion sur chaque nouvelle page où cela est nécessaire. La connexion n est pas permanente. Il faudra donc écrire l instruction ci-dessus autant de fois que nécessaire, et en cas de changement de base de données, il faudra modifier chacune des connexions avec les nouveaux paramètres. Ce qui va à l encontre de la logique de programmation et de non duplication des éléments. Une solution consiste donc à définir des constantes PHP. Une constante est une variable particulière qui ne peut pas varier pendant l exécution du script PHP. L intérêt va donc être de définir une constante pour chacun des 4 paramètres et ensuite utiliser cette constante quand cela sera nécessaire. De cette manière, il n y aura qu un seul endroit ou modifier les informations. La syntaxe est la suivante : L usage veut que le nom d une constante soit en majuscule. A noter qu une constante ne commence pas par un $. Dans notre cas, un fichier type de constante pourrait être : Ces éléments sont sauvegardés dans un fichier que l on peut appeler config.inc.php. Ce fichier contiendra toutes nos constantes. Il faut ensuite 2
2 define('nom_constante', 'valeur'); Listing 2: Déclaration d une constante en PHP 2 define('bdd_user', 'monlogin'); 3 define('bdd_pass', 'monpassword'); 4 define('bdd_serveur', 'localhost'); 5 define('bdd_bdd', 'basededonnees'); Listing 3: Exemple de fichier config.inc.php inclure ce fichier à chaque fois que l on va faire une connexion à notre base de données. Ce qui pourrait donner le code suivant : 1... 2 <?php 3 include('config.inc.php'); 4 $bdd = new PDO('mysql:host='.BDD_SERVEUR.';dbname='.BDD_BDD.'; 5 charset=utf8', BDD_USER, BDD_PASS); 6... Listing 4: Exemple de fichier 2 Récupérer des données 2.1 Exécuter une requête Explication des lignes : 1. Cette ligne permet d écrire la requête au format MySQL. Une requête est avant tout du texte! Il est donc possible de construire cette phrase en concaténant des variables. 3
2 $requete = 'SELECT * FROM table'; 3 $exe = $bdd->query($requete); Listing 5: Exécuter une requête 2. Cette ligne exécute la requête précédemment écrite. C est à ce moment là que le résultat de la requête est récupéré dans la variable $exe. Il n est techniquement pas nécessaire de passer par une variable intermédiaire pour écrire la requête SQL (la variable $requete). Cependant vous utiliserez TOUJOURS cette solution durant ce semestre. Il sera ainsi beaucoup plus facile de débuguer et comprendre ce qui se passe en affichant, dans le navigateur, la requête. 2.2 Afficher le résultat d une requête La variable $exe contient donc le résultat de notre requête. Ce résultat, si la requête a réussi, est un tableau composé des lignes de la base de données correspondant à la selection. Il faut donc parcourir ce tableau afin d afficher chacune des lignes. Il y a deux méthodes pour réaliser cela : Compter le nombre total d élément dans le tableau, et faire une boucle for Parcourir le tableau jusqu à ce qu il n y ait plus d éléments. 2.2.1 Parcourir avec une boucle for Explication des lignes ligne 1 : Écriture de notre requête dans une variable ligne 2 : Exécution de la requête pour récupérer les réponses ligne 4 : Comptage du nombre de réponse de la requête. On pourrait utiliser cette variable pour afficher le nombre de réponse à l utilisateur. ligne 6 : Déclaration d une boucle for qui va permettre de parcourir toutes les réponses ligne 8 : Cette ligne permet de récupérer une ligne parmi l ensemble des lignes du tableau. fetch signifiant va chercher. A chaque itération de la boucle, on va chercher la ligne suivante dans le tableau des réponses. La notation -> est une notation objet. Vous la comprendrez mieux lors du prochain semestre. 4
2 $requete = 'SELECT * FROM table'; 3 $exe = $db->query($requete); 4 5 $nbreponses = $exe->rowcount(); 6 7 for($i=0; $i<$nbresponses; $i++) 8 { 9 $ligne = $exe->fetch(); 10 echo '<p>'.$ligne['champ1'].' '.$ligne['champ2'].'</p>'; 11 } Listing 6: Parcourir avec une boucle for ligne 9 : On affiche les données. A noter que la variable $ligne est un tableau associatif dont la clé est le nom du champ de votre table. 2.2.2 Parcourir avec une boucle while 2 $requete = 'SELECT * FROM table'; 3 $exe = $db->query($requete); 4 5 while($ligne = $exe->fetch()) 6 { 7 echo '<p>'.$ligne['champ1'].' '.$ligne['champ2'].'</p>'; 8 } Listing 7: Parcourir avec une boucle while Explication des lignes ligne 1 : Écriture de notre requête dans une variable ligne 2 : Exécution de la requête pour récupérer les réponses ligne 4 :Déclaration d une boucle while. Cette boucle va s exécuter tant qu il y a des valeurs dans le tableau $exe, tant que le fetch arrive à aller chercher une ligne. ligne 6 : On affiche les données. A noter que la variable $ligne est un tableau associatif dont la clé est le nom du champ de votre table. 5
2.3 Les erreurs Une erreur classique, que vous rencontrerez ressemblera à : 1 Fatal error: Call to a member function fetch() on a 2 non-object in C:\wamp\www\tests\index.php on line 13 Listing 8: Message d erreur Cette erreur apparait sur la ligne du fetch, mais en fait elle signifie que la ligne récupérée (quelque soit la méthode utilisée) est vide (Null). La cause de cela est quasiment toujours le fait que votre requête comporte une erreur et qu elle renvoie un résultat vide. Affichez donc votre requête grâce à : 2 echo $req; Listing 9: Afficher la requête Copier/coller la réponse dans phpmyadmin, onglet SQL afin de tester la requête et obtenir un message d erreur plus précis. 3 Exercice 3.1 Ennoncé Structure de la table comics : Nom Type Commentaire id int clé primaire titre varchar(150) collection varchar(150) nbpages int 0 par défaut prix double 1. Créer une nouvelle table dans votre base de données que vous nommerez comics. Ajouter les champs du tableau précédent. 6
2. Récupérer le fichier comics.csv sur davidannebicque.fr. 3. Vérifiez l ordre des champs et importez les données dans votre table. 4. Préparez votre fichier config.inc.php avec vos constantes. 5. Écrire un fichier index.php qui va afficher le contenu de la table comics dans un tableau HTML. 6. Obtenir le résultat ci-dessous. 7
3.2 Questions Bonus 1. Ajouter le montant total de la collection en bas du tableau 2. Ajouter le prix moyen d un album en bas du tableau. 3. Écrire un fichier qui affiche de manière unique les collections présentes dans la table comics. 4 Insérer des données dans une table L insertion de données dans une table passe par une requête SQL de type : INSERT INTO table (liste des champs) VALUES (valeur des champs) Listing 10: Requête INSERT L ordre des champs doit être le même que l ordre des valeurs. On ne précise pas les champs de type auto incrémenté, car ils sont gérés automatiquement par la base de données. Afin de rendre cette requête dynamique les valeurs des champs proviennent d éléments issus de l utilisateur (remplissant d un formulaire, choix d article dans un panier,...), ou de données calculées par le site web (nombre de clics par exemple). Il faut donc pouvoir construire une requête qui va comporter des variables PHP comme valeur. Cela se fait très classiquement puisque la requête est en fait une chaîne de caractère. Il faut donc concaténer les variables PHP au reste de la chaîne, comme dans l exemple ci-dessous : 2 $req = 'INSERT INTO table (nom_champ1, nom_champ2) VALUES 3 ("'.$champ1.'","'.$_get['champ2'].'")'; Listing 11: Requête INSERT Il faut noter dans cette expression le fait que les valeurs soient encadrées par des, ceci est obligatoire dans le cas de champs texte. Ne pas les mettre provoque une erreur. Pour des raisons pratiques d écriture on utilisera toujours les simples quotes, pour encadrer cette chaîne. L exécution de cette requête est effectuée avec la méthode query comme précédemment. 8
2 $exe = $bdd->query($req); Listing 12: Requête INSERT On prend le soin de stocker le résultat de l exécution dans une variable afin de pouvoir contrôler la bonne exécution de la requête. 5 Exercices 1. Tester une requête d insert pour la table comics 2. Ecrire un formulaire qui permet la saisie des données 3. Ecrire la page de traitement qui permette l insertion des données du formulaire dans la base de données. 9