PHP et MySQL PHP et les bases de données * SQL: Structured Query Language * Langage universel des bases de données * Permet l'interrogation d'une base * Permet la modification d'une base * MySQL * Gestionnaire de bases de données * Commandé par le langage SQL * PHP peut interagir avec MySQL * Envoi de requêtes SQL * Récupération du résultat * Ajout de données * phpMyAdmin * Interface Web pour accéder à MySQL * Facilite la gestion des bases * Permet de tester ses requêtes Bases de données: vocabulaire Types d'attributs particuliers * Attribut en clé primaire * Identifiant unique d'un enregistrement * Accès direct à l'enregistrement par la clé * Accélère les jointures où la clé sert de pivot * Attribut en index * N'est pas forcément unique dans la table * Accélère les tris (ou recherches) sur l'attribut * Sans index: recherche séquentielle * Avec index: table organisée en zones Requêtes SQL: projection * Sélection de certains attributs d'une table * SELECT titre,auteur FROM ouvrage * "*" signifie tous les attributs * SELECT * FROM ouvrage Requêtes SQL: sélection (1/2) * Sélection d'enregistrements d'une table vérifiant certaines conditions * SELECT * FROM ouvrage WHERE auteur='Lévy, Marc' Requêtes SQL: sélection (2/2) * Les conditions peuvent être combinées * Avec "AND" et "OR" * SELECT * FROM ouvrage WHERE (auteur='Lévy, Marc' OR auteur='Harris, Thomas') * Possibilité de filtre * "%" = caractères joker * SELECT * FROM ouvrage WHERE (auteur LIKE '%Marc%') * Tous les auteurs avec "Marc" dans le nom * SELECT * FROM ouvrage WHERE (auteur LIKE 'H%') * Tous les auteurs avec un nom commençant par "H" Requêtes SQL: tri (1/2) * A la suite d'une requête: mot-clé "ORDER BY" * SELECT * FROM utilisateur ORDER BY nom,prenom * Tri sur le premier attribut ("nom") * Puis, tri sur le second ("prenom") * ... Requêtes SQL: tri (2/2) * Ordre croissant par défaut * Lexicographique pour les chaînes * Décroissant avec le mot-clé "DESC" * Mot à placer après l'attribut concerné * SELECT * FROM utilisateur ORDER BY nom DESC, prenom DESC * Accélération d'un tri * Déclarer l'attribut concerné comme index * Mais cela prend plus d'espace Requêtes SQL: jointure (1/3) * Fusion de plusieurs tables * SELECT ouvrage.titre, utilisateur.nom, utilisateur.prenom FROM ouvrage,emprunt,utilisateur WHERE (utilisateur.id=emprunt.utilisateur AND ouvrage.id=emprunt.ouvrage) Requêtes SQL: jointure (2/3) Requêtes SQL: jointure (3/3) * Comment distinguer les attributs de même nom ? * Mot-clé "AS" pour renommer l'attribut dans la projection * SELECT *,ouvrage.id AS ouvrage_id, emprunt.id AS emprunt_id FROM ... Requêtes SQL: insertion * Solution 1 * INSERT INTO ouvrage (titre,auteur) VALUES ('Sphère','Crichton, Michael') * Les attributs sont précisés * Une valeur est affectée à chacun * Si un attribut est manquant, une valeur par défaut est attribuée * Solution 2 * INSERT INTO ouvrage VALUES (NULL,'Sphère', 'Crichton, Michael') * Les attributs ne sont pas précisés * Valeurs affectées selon l'ordre des attributs dans la table * Si aucune valeur n'est fournie, une valeur par défaut est attribuée * Valeur par défaut * Soit valeur nulle * Chaîne vide ou zéro * Soit valeur fixée * Indiquée dans la définition de la table * Soit valeur entière auto-incrémentée * Utilisée pour l'attribution automatique d'une clé primaire Requêtes SQL: suppression & mise à jour * Plusieurs enregistrements peuvent être supprimés dans une seule requête ! * DELETE FROM utilisateur WHERE nom='Nawouak' * Suppression de tous les enregistrements avec le nom "Nawouak" * Pour être sûr de supprimer le bon enregistrement, utiliser sa clé primaire * DELETE FROM emprunt WHERE id=2 * Suppression de l'enregistrement avec l'identifiant unique "2" * Idem pour la mise à jour * UPDATE emprunt SET utilisateur=7 * Tous les livres sont maintenant empruntés par l'utilisateur "7" * UPDATE emprunt SET utilisateur=7 WHERE ouvrage=2 * Le livre "2" est maintenant emprunté par l'utilisateur "7" phpMyAdmin: interface d'administration * Interface Web d'administration MySQL * Niveau administrateur * Créer des utilisateurs * Login / mot de passe * Limitation de l'accès à certaines bases * Créer des bases * En général, un utilisateur = une base * Cas de la plupart des fournisseurs d'espace * Niveau utilisateur * Accès à une ou plusieurs bases * Souvent impossible de créer de nouvelles bases * Manipulation de tables * Définition de leur structure * Saisie des données * Requêtes phpMyAdmin: contenu d'une base (1/2) phpMyAdmin: structure d'une table phpMyAdmin: structure d'un attribut phpMyAdmin: contenu d'une base (2/2) phpMyAdmin: contenu d'une table phpMyAdmin: modification d'un enregistrement phpMyAdmin: exporter une base phpMyAdmin: importer une base Connexion à un serveur MySQL (1/2) * PHP et MySQL peuvent être sur des serveurs différents * Informations nécessaires * Nom du serveur ("host") * Si même serveur, host = "localhost" * Identifiant de l'utilisateur ("login") * Mot de passe ("password") * Informations par défaut dans EasyPHP * login = "root" * password = "" * Problème de sécurité ==> changer le mot de passe Connexion à un serveur MySQL (2/2) * Fonction "mysqli_connect" * Nécessite host, login et password * Retourne l'identifiant de la connexion * Connexion échouée ==> retourne "FALSE" * Un message est affiché dans le navigateur * Mode silencieux: @mysqli_connect * "@" empêche l'affichage des erreurs de la fonction qui suit * Exemple d'utilisation $cnx = @mysqli_connect($host,$login,$password); if ($cnx) { /* Connexion établie */ } else die("Connexion au serveur impossible !"); * "die" affiche un message et interrompt le script PHP Déconnexion du serveur MySQL * Nombre de connexions souvent limité * Pensez aux autres ! * Se déconnecter le plus tôt possible * Penser à se déconnecter même en cas d'erreur * Fonction "mysqli_close" * Fournir l'identifiant de la connexion * Exemple d'utilisation $cnx = @mysqli_connect($host,$login,$password); if ($cnx) { /* Connexion établie */ ... @mysqli_close($cnx); } Sélection d'une base de données * Fonction "mysqli_select_db" * Nécessite le nom de la base ("base") * Retourne "TRUE" si la sélection a réussie * Exemple d'utilisation if (@mysqli_select_db($cnx,$base)) { /* Sélection réussie */ } else { @mysqli_close($cnx); die("Sélection de la base impossible !"); } * Les requêtes se feront sur la base sélectionnée * Possibilité de se connecter à plusieurs bases en cours d'exécution * Mais généralement on travaille sur une seule base Script complet de connexion (1/3) * Connexion et sélection d'une base de données $cnx = @mysqli_connect($host,$login,$password); if ($cnx) { if (@mysqli_select_db($cnx,$base)) { /* Connexion établie */ ... // Code du script @mysqli_close($cnx); } else { @mysqli_close($cnx); die("Sélection de la base impossible !"); } } else die("Connexion au serveur impossible !"); Script complet de connexion (2/3) * Script utilisé plusieurs fois * A exécuter dans chaque page qui fait une requête * Ecrire une fonction "connexion" * Permet d'éviter la recopie dans plusieurs pages * Permet d'isoler les identifiants * Différents entre site de test et site de production * Placer la fonction dans un fichier: connexion.php * Utilisation du fichier include("connexion.php"); $cnx = connexion(); /* Requêtes sur la base */ @mysqli_close($cnx); Script complet de connexion (3/3) * Fichier "connexion.php" <?php function connexion() { $host = "..."; $login = "..."; $password = "..."; $base = "..."; $cnx = @mysqli_connect($host,$login,$password); if ($cnx) { if (@mysqli_select_db($cnx,$base)) return $cnx; else { @mysqli_close($cnx); die("Sélection de la base impossible !"); } } else die("Connexion au serveur impossible !"); } ?> Exécuter une requête SQL * Requête SQL placée dans une chaîne de caractères * $requete = "SELECT * FROM utilisateur"; * Exécution de la requête avec "mysqli_query" * $result = @mysqli_query($cnx,$requete); * Retourne le résultat de la requête * Si la requête a échoué, retourne "FALSE" * Sinon "$result" contient le résultat * Connaître le nombre d'enregistrements * Requête "SELECT" * Nombre d'éléments trouvés $nb = @mysqli_num_rows($result); * Requêtes "DELETE" et "UPDATE" * Nombre d'éléments affectés $nb = @mysqli_affected_rows($cnx); Parcourir le résultat d'une requête (1/4) * Lecture des enregistrements un par un: mysqli_fetch_? * $enr = @mysqli_fetch_?($result); * "$enr" représente un enregistement * Cet enregistrement est retiré de "$result" * Retourne "FALSE" si "$result" est vide * Parcours des enregistrements * while ($enr = @mysqli_fetch_?($result)) { ... } * Plusieurs possibilités pour représenter un enregistrement * Sous forme de tableau simple: mysqli_fetch_row * Sous forme de tableau associatif: mysqli_fetch_assoc * Sous forme d'objet: mysqli_fetch_object Parcourir le résultat d'une requête (2/4) * Option 1: enregistrement = tableau simple $requete = "SELECT * FROM utilisateur"; $result = @mysqli_query($cnx,$requete); if (!$result) { @mysqli_close($cnx); die("La requête a échoué !"); } while ($enr = @mysqli_fetch_row($result)) { echo "<p>Utilisateur $enr[0]: $enr[1], $enr[2]</p>"; } * Résultat <p>Utilisateur 1: Dupont, Jean</p> <p>Utilisateur 2: Martin, Pierre</p> <p>Utilisateur 3: Nawouak, Bruno</p> Parcourir le résultat d'une requête (3/4) * Option 2: enregistrement = tableau associatif while ($enr = @mysqli_fetch_assoc($result)) { echo "<p>Utilisateur $enr['id']: "; echo "$enr['nom'], $enr['prenom']</p>"; } * Option 3: enregistrement = objet while ($enr = @mysqli_fetch_object($result)) { echo "<p>Utilisateur $enr->id: "; echo "$enr->nom, $enr->prenom</p>"; } Parcourir le résultat d'une requête (4/4) * Comment choisir une option ? * Ordre des attributs * Ne peut pas être changé avec l'option 1 * N'a aucune importance pour les options 2 et 3 * Noms des attributs * N'ont aucune importance pour l'option 1 * Peuvent être changés avec l'option 2 * A condition d'être stockés dans des variables * Ne peuvent pas être changés avec l'option 3 * Facilité d'écriture * La plus condensée: option 1 * La plus longue: option 2 * La plus lisible: option 3 Gérer une requête d'insertion * Exemple d'une insertion $requete = "INSERT INTO utilisateur VALUES (NULL,'Martin','Arthur')"; $result = @mysqli_query($cnx,$requete); * L'index du nouvel enregistrement peut être utile * Mais comment le récupérer si il est incrémenté automatiquement ? * $id = @mysqli_insert_id($cnx); * Retourne la valeur de l'attribut en auto-incrément |