TP PHP : Bases de données et interfaces web
Transcription
TP PHP : Bases de données et interfaces web
TP PHP : Bases de données et interfaces web Nicolas Moyroud 18 juin 2008 1 Présentation générale du TP 1.1 Contexte et objectifs du TP Avec le langage PHP, vous allez réaliser des interfaces web qui vont permettre d'acher et de gérer des données dans la base PostgreSQL. Les programmes developpés devront suivre une architecture respectant la séparation entre les couches d'accès aux données et de présentation. Vous allez commencer par créer un programme qui ache le contenu d'une table puis de toutes les tables de la base dans une page HTML. Vous réutiliserez ensuite la partie présentation de ce programme pour acher le résultat d'une requête qui porte sur plusieurs tables. Dans la dernière partie, vous allez réaliser des interfaces web qui proposent des formulaires pour la saisie et la suppression de données dans les tables. 1.2 1.3 Principales étapes à réaliser récupérer les enregistrements dans une table, acher les données dans une page HTML, exécuter une requête multi-tables et acher le résultat, créer un formulaire de saisie de données, ajouter une fonction de suppression des données. Matériel et logiciels nécessaires On dispose pour ce travail : d'un PC sous Windows, d'un serveur web Apache local avec son module PHP activé (WampServer), du SGBD PostgreSQL et son interface d'administration phpPgAdmin. 1.4 Données fournies Toutes les données manipulées sont contenues dans une base de données PostgreSQL. 1 2 Achage du contenu des tables de la base Vous allez réaliser un programme PHP qui parcours une table de la base et ache les données sur une interface web. Vous séparerez la couche d'accès et la couche de présentation des données. Pour nir, vous écrirez un code générique capable d'acher les enregistrements contenus dans n'importe quelle table de la base. Démarche Vériez le serveur et créez un nouveau dossier Ecrivez un code de connexion à la base PostgreSQL Manipulation Vériez que les services de Wampserver sont toujours actifs. Si ce n'est pas le cas, démarrez les. Avec l'explorateur de chiers, ouvrez le répertoire C:\wamp\www\ird et ajoutez y un sous-répertoire ihm. Pour toute la suite de ce TP, vous travaillerez dans ce dossier. Ouvrez l'éditeur de code Notepad++ (Tous les Programmes>Notepad++>Notepad++ ) et créez y un nouveau chier. Ecrivez un code PHP qui lance une connexion à la base grâce à la fonction pg_connect et stocke la connexion dans une variable $dbconn. Vous gèrerez les cas d'erreurs avec un message. Sauvegardez le chier avec le nom connectDB.php. Voici ce que vous devriez obtenir : php $dbconn <? if = pg_connect ( ' host = localhost dbname = isotopes user = postgres password = postgres ' ) ; ( ! $dbconn ) { echo ' Erreur de connexion ' ; exit ; } ?> Exécutez une requête SQL avec PHP Ecrivez une requête SQL de sélection des enregistrements de la table Peche. Exécutez la avec PHP dans votre base de données PostgreSQL, en utilisant la fonction pg_query. Vous récupèrerez le résultat de la requête dans une variable $result. Sauvegardez le chier avec le nom tableDAO.php. Voici ce que vous devriez obtenir : $requete = " SELECT * FROM peche " ; $result = pg_query ( $dbconn , $requete ) ; if ( ! $result ) { echo ' Erreur de requete ' ; exit ; } Chargez les noms des champs renvoyés Dans le même chier, ajoutez un code qui parcours la variable $result pour charger les noms des champs renvoyés dans un tableau PHP $eldsName (utilisez les fonctions pg_num_elds et pg_eld_name) : $num_fields = pg_num_fields ( $result ) ; for ( $col = 0 ; $col < $num_fields ; $col ++) { $fieldsName [ ] = pg_field_name ( $result , $col ) ; } 2 Achez les données dans une page HTML Vous allez maintenant créer la couche de présentation qui ache dans une page HTML les données récupérées à l'étape précédente. Créez un nouveau chier printData.php et parcourez la variable $result avec la fonction pg_fetch_row pour créer une table HTML. Vous utiliserez le tableau PHP $eldsName pour achez sur la première ligne les noms des colonnes. En-dessous de la table HTML, vous indiquerez le nombre d'enregistrements achés en utilisant la fonction pg_num_rows. html ><head ></head > body > < table border="1" cellspacing="0"><tr><th> <? php echo implode ( ' </th >< th > ' , $fieldsName ) ; echo ' </th > </ tr > ' ; while ( $row = pg_fetch_row ( $result ) ) { echo '<tr ><td > ' ; echo implode ( '& nbsp ; </ td >< td > ' , $row ) ; echo '& nbsp ; </ td > </ tr > ' ; < < } echo ' </ table >< br /> ' ; $rowsCount = pg_num_rows ( $result ) ; echo " Nombre d ' enregistrements : <b >" ?> </ Ecrivez le programme principal . $rowsCount . " </b >" ; body ></html > Il vous reste à écrire le programme principal consult.php qui va appeler les trois codes réalisés ci-dessus. php require require require <? ' connectDB . php ' ) ; ' tableDAO . php ' ) ; ( ' printData . php ' ) ; ( ( ?> Améliorez la généricité du programme Chargez la page http://localhost/ird/ihm/consult.php dans le navigateur Firefox et vériez que les données de la table Peche sont achées. La structure du code développé présente le gros avantage d'être générique : si vous souhaitez acher les données d'une autre table, il sut de changer le nom de la table dans la requête SQL. Plutôt que d'avoir à éditer le code tableDAO.php à chaque fois que vous souhaitez acher une table, vous allez modier le programme consult.php pour qu'il récupère le nom de la table grâce à la valeur transmise par $_GET['tableName']. On vériera les valeurs possibles de cette variable grâce à une liste des tables autorisées (campagne, peche, individu, taxonomie, prelevements). Modiez également le programme tableDAO.php pour utiliser cette variable comme nom de table dans la requête SQL . consult.php php $allowedTables <? array ( ' campagne ' , ' peche ' , ' individu ' , ' taxonomie ' , ' prelevements ' ) ; if ( ! isset ( $_GET [ ' tableName ' ] ) | | ! in_array ( $_GET [ ' tableName ' ] , $allowedTables ) ) { $_GET [ ' tableName ' ] = campagne ; } require require require = ' connectDB . php ' ) ; ' tableDAO . php ' ) ; ( ' printData . php ' ) ; ( ( ?> tableDAO.php $requete = " SELECT * FROM " . $_GET [ ' tableName ' ] ; Chargez la page http://localhost/ird/ihm/consult.php?tableName=individu dans le navigateur Firefox et vériez que les données de la table Individu sont bien achées. 3 3 Création d'une interface de requête multi-table L'objectif de cette partie sera de réaliser un formulaire pour rechercher des informations sur les individus contenus dans la base de données. Les critères de sélections seront proposés grâce à trois listes déroulantes qui portent respectivement sur le type du prélèvement, la localisation de la pêche et l'espèce concernée. Les résultats seront achés dans une page HTML. Démarche Remplissez les listes déroulantes Manipulation Vous allez commencer par créer un programme PHP chargé de remplir les listes déroulantes qui vont être utilisées dans le formulaire de recherche. Créez un chier fillLists.php et écrivez y trois fonctions chargée de remplir chacune des listes : llPrelevementList, llLocalisationList et llEspeceList. La première liste sera remplie directement en fournissant directement dans le code les valeurs possibles (voir dans le dictionnaire des données la liste type_prélèvement). La deuxième sera remplie grâce à une requête sur le champ localisation de la table Peche, en prenant soin de supprimer les doublons. La troisième liste sera remplie à partir des champs ID_espece et nom_espece_latin de la table taxonomie. La deuxième et la troisième fonction prendront comme paramètre la variable $dbconn qui contient la connexion à la base. function fillPrelevementList ( ) { return array ( 'MB ' => ' muscle blanc ' , 'FO ' => ' foie ' , 'SG ' => ' sang ' , 'PE ' => ' paroi estomac ' , 'PR ' => ' proie ' , 'AN ' => ' anatife ' ) ; } function fillLocalisationList ( $dbconn ) { $localisationList = array ( ) ; $requete = " SELECT DISTINCT localisation FROM peche " ; $result = pg_query ( $dbconn , $requete ) ; if ( ! $result ) { echo ' Erreur de requete ' ; exit ; } while ( $row = pg_fetch_row ( $result ) ) { $localisation = $row [ 0 ] ; $cle_localisation = $row [ 0 ] ; if ( trim ( $localisation ) == '' ) { $localisation = ' -- Inconnue - - ' ; $cle_localisation = ' NULL ' ; } $localisationList [ $cle_localisation ] = $localisation ; } return $localisationList ; } function fillEspeceList ( $dbconn ) { $especeList = array ( ) ; $requete = " SELECT ID_espece , nom_espece_latin FROM taxonomie " ; $result = pg_query ( $dbconn , $requete ) ; if ( ! $result ) { echo ' Erreur de requete ' ; exit ; } while ( $row = pg_fetch_row ( $result ) ) { $ID_espece = $row [ 0 ] ; $nom_espece_latin = $row [ 1 ] ; $especeList [ $ID_espece ] = $nom_espece_latin ; } return $especeList ; } 4 Créez un formulaire de recherche avec HTML_Quickform Vous pouvez maintenant utiliser la classe PHP HTML_QuickForm pour créer un formulaire qui contient les trois listes déroulantes ci-dessus. Nommez le chier individu.php et incluez le chier HTML/QuickForm.php. Créez un formulaire avec les 3 listes déroulantes et un bouton d'envoi. Pour le traitement du formulaire, contentez vous d'appeler (avec l'instruction include) un programme searchIndividu.php et le programme printData.php qui achera les données. Voici une solution possible : php require ' connectDB . php ' ; require ' fillLists . php ' ; require ' HTML / QuickForm . php ' ; <? $listPrelevement = fillPrelevementList ( ) ; $listLocalisation = fillLocalisationList ( $dbconn ) ; $listEspece = fillEspeceList ( $dbconn ) ; $form = new HTML_QuickForm ( ' formSearchIndividu ' , ' post ' ) ; $form −>addElement ( ' header ' , null , " Recherche d ' individus " ) ; $form −>addElement ( ' select ' , ' prelevement ' , ' Type de prelevement ' , $listPrelevement ) ; $form −>addElement ( ' select ' , ' localisation ' , ' Localisation de la peche ' , $listLocalisation ) ; $form −>addElement ( ' select ' , ' espece ' , ' Espece ' , $listEspece ) ; $form −>addElement ( ' submit ' , null , ' Rechercher ' ) ; $form −>applyFilter ( ' __ALL__ ' , ' trim ' ) ; $form −>applyFilter ( ' __ALL__ ' , ' pg_escape_string ' ) ; if ( $form −>validate ( ) ) { / / i c i on include ' searchIndividu . php ' ; include ' printData . php ' ; lancera le traitement } else { $form −>display ( ) ; // } ?> 5 affichage du formulaire Exécutez la requête avec les critères issus du formulaire Il vous faut maintenant créer le programme searchIndividu.php pour utiliser les valeurs du formulaire et exécuter une requête dans la base. La requête doit retourner les données suivantes : depuis la table taxonomie le champ nom_espece_latin, depuis la table individu les champs taille_lf_individu, poids_individu, sexe_individu, heure_capture, depuis la table peche le champ date_peche et depuis la table prelevements les champs c, n, dc, dn et c_n. On classera les résultats dans l'ordre inverse des dates et heures de capture (du plus ancien au plus récent). Les données n'ont pas besoin d'être achées dans ce programme (elles le sont déjà grâce à l'appel de printData.php). php $requete = " SELECT nom_espece_latin , taille_LF_individu , poids_individu , sexe_individu , heure_capture , date_peche , c , n , dc , dn , c_n FROM peche AS pec , individu AS ind , taxonomie AS tax , prelevements AS pre WHERE ind . ID_peche = pec . ID_peche AND ind . ID_espece = tax . ID_espece AND ind . ID_individu = pre . ID_individu AND pre . type_prelevement = '" . $_POST [ ' prelevement ' ] . " ' AND pec . localisation = '" . $_POST [ ' localisation ' ] . " ' AND tax . ID_espece = " . $_POST [ ' espece ' ] . " ORDER BY date_peche , heure_capture DESC "; <? $result = pg_query ( $dbconn , $requete ) ; if ( ! $result ) { echo ' Erreur de requete ' ; exit ; } $num_fields = pg_num_fields ( $result ) ; for ( $col = 0 ; $col < $num_fields ; $col ++) { $fieldsName [ ] = pg_field_name ( $result , $col ) ; } ?> Avec le navigateur Firefox, testez le fonctionnement de la recherche en saisissant l'URL http://localhost/ird/ihm/individu.php. Essayez plusieurs critères de recherche diérents. 6 4 Ajout d'une interface sécurisée pour la saisie d'enregistrements Dans cette dernière partie, vous allez créer une interface pour la saisie d'enregistrements dans la table Peche. Pour commencer, il va falloir mettre en place un mécanisme d'authentication pour n'autoriser l'accès qu'à certains utilisateurs autorisés. Démarche Création d'une liste d'utilisateurs dans la base Manipulation Vous allez ajouter dans la base une nouvelle table qui va contenir les utilisateurs autorisés à saisir des informations. Exécutez le code SQL suivant dans la base de données : ∗ ∗ ∗ Table : u t i l i s a t e u r ∗/ / ∗==============================================================∗ / / ============================================================== / / create table utilisateur ( ID SERIAL not null , login VARCHAR ( 1 0 ) not null , password VARCHAR ( 3 2 ) not null , userlevel INT4 not null , constraint PK_UTILISATEUR primary key ( ID ) ); INSERT INTO utilisateur ( login , password , userlevel ) VALUES ( ' user0 ' , ' 21291505 ea7d2cc217ee680b1a611f4a ' INSERT INTO utilisateur ( login , password , userlevel ) VALUES ( ' user1 ' , ' dfd88155fc25d8025550db1c425089da ' INSERT INTO utilisateur ( login , password , userlevel ) VALUES ( ' user2 ' , ' 654628 c08e6ab1799c96d2f16719af0a ' Utilisation de la classe AccessControl pour sécuriser l'accès à une page ,0); ,1); ,2); Copiez le chier AccessControl.class.php dans le répertoire C:\wamp\www\ird\ihm. Créez un nouveau programme formPeche.php qui inclut les chiers connectDB.php et AccessControl.class.php. Dans une variable $acl, créez une nouvelle instance de la classe AccessControl avec les paramètres $dbconn, 'utilisateur' et 1 (respectivement la connexion à la base, le nom de la table des utilisateurs et le niveau maximum autorisé pour l'accès à la page). Lancez la méthode run() de l'objet $acl et faites achez un simple message de test en-dessous. php require ' connectDB . php ' ; require ' AccessControl . class . php ' ; <? $acl = & new AccessControl ( $dbconn , ' utilisateur ' $acl −> run ( ) ; ,1); echo 'La connexion marche ' ; ?> Avec le navigateur Firefox, saisissez l'URL suivante : http://localhost/ird/ihm/formPeche.php. Essayez de vous connecter avec le login user2, mot de passe tititi. Essayez avec le login user1, mot de passe tatata. Essayez avec le login user0, mot de passe tototo. Editez le code de formPeche.php et mettez la valeur 0 pour le 3ème paramètre de la classe AccessControl. Recommencez les 3 tests de connexion. Conclusion ? 7 Création du formulaire de saisie pour la table Peche Supprimez le message de test dans le code précédent et utilisez la classe HTML_QuickForm pour créer un formulaire de saisie des valeurs de la table Peche. Il contiendra plusieurs zone de saisie texte libre pour les champs : date_peche, saison, association, position_peche, latitude_peche, longitude_peche. Il contiendra également deux listes déroulantes pour sélectionner la campagne et l'association. Pour le contenu de ces listes, vous incluerez le programme fillLists.php dans lequel vous ajouterez deux fonctions llCampagneList et llAssociationList (pour le contenu de cette dernière voir le dictionnaire des données). Le champ saison sera déni comme obligatoire dans le formulaire. Vous utiliserez le type d'élément de formulaire date pour le champ date_peche. Dans le cas où le formulaire est validé, vous incluerez le chier insertPeche.php qui insèrera les valeurs saisies. fillLists.php function fillCampagneList ( $dbconn ) { $campagneList = array ( ) ; $requete = " SELECT ID_campagne FROM campagne " ; $result = pg_query ( $dbconn , $requete ) ; if ( ! $result ) { echo ' Erreur de requete ' ; exit ; } while ( $row = pg_fetch_row ( $result ) ) $campagneList [ $row [ 0 ] ] = $row [ 0 ] ; { } return $campagneList ; } function fillAssociationList ( ) { return array ( 'R ' => ' Radeau ' , 'L ' => ' Libre ' , 'P ' => ' Palangre ' , 'T ' => ' Traine ' , 'C ' => ' Chalut ' ) ; } 8 formPeche.php php require require require require <? ' connectDB . php ' ; ' AccessControl . class . php ' ; ' HTML / QuickForm . php ' ; ' fillLists . php ' ; $acl = & new AccessControl ( $dbconn , ' utilisateur ' $acl −> run ( ) ; ,1); $listCampagne = fillCampagneList ( $dbconn ) ; $listAssoc = fillAssociationList ( ) ; $form = new HTML_QuickForm ( ' formInsertPeche ' , ' post ' ) ; $form −>addElement ( ' header ' , null , " Saisie d ' une peche " ) ; $form −>addElement ( ' select ' , ' campagne ' , ' Campagne ' , $listCampagne ) ; $form −>addElement ( ' text ' , ' ref_peche_campagne ' , ' Ref peche / campagne ' , array ( ' size ' =>20, ' maxlength ' = > 3 0 ) ) ; $options = array ( ' language ' => 'fr ' , ' format ' => ' dMY ' , ' minYear ' => 2 0 0 0 , ' maxYear ' => 2 0 1 0 ) ; $form −>addElement ( ' date ' , ' date_peche ' , ' Date de la peche ' , $options ) ; $form −>addElement ( ' text ' , ' saison ' , ' Saison ' , array ( ' size ' =>5, ' maxlength ' = > 2 ) ) ; $form −>addElement ( ' select ' , ' association ' , ' Association ' , $listAssoc ) ; $form −>addElement ( ' text ' , ' localisation ' , ' Localisation de la peche ' , array ( ' size ' =>20, ' maxlength ' = > 3 0 ) ) ; $form −>addElement ( ' text ' , ' latitude ' , ' Latitude ' , array ( ' size ' =>10, ' maxlength ' = > 1 0 ) ) ; $form −>addElement ( ' text ' , ' longitude ' , ' Longitude ' , array ( ' size ' =>10, ' maxlength ' = > 1 0 ) ) ; $form −>addElement ( ' submit ' , ' btnSubmit ' , ' Envoyer ' ) ; $form −>applyFilter ( ' __ALL__ ' , ' trim ' ) ; $form −>applyFilter ( ' __ALL__ ' , ' pg_escape_string ' ) ; $form −>addRule ( ' saison ' , ' Vous devez saisir une saison ' , ' required ' , '' , ' client ' ) ; $form −>addRule ( ' latitude ' , 'La latitude est une valeur numerique ' , ' numeric ' , '' , ' client ' ) ; $form −>addRule ( ' longitude ' , 'La longitude est une valeur numerique ' , ' numeric ' , '' , ' client ' ) ; $form −>setRequiredNote ( '* = champs obligatoires ' ) ; $form −>setJsWarnings ( ' Erreur de saisie ' , ' Veuillez corriger ' ) ; if } $form −>validate ( ) ) { / / i c i on l a n c e r a l ' i n s e r t i o n include ' insertPeche . php ' ; else { $form −>display ( ) ; / / a f f i c h a g e du f o r m u l a i r e ( } ?> 9 Exécutez la requête SQL d'insertion dans la base Créez le programme insertPeche.php pour insérer dans la base les valeurs envoyées depuis le formulaire précédent. Vous traiterez le champ date_peche pour insérer la date au format YYYY-MM-DD. Dans le cas où les valeurs de latitude et longitude n'ont pas été saisies, vous insèrerez NULL dans les colonnes correspondantes de la base. php $date = $_POST [ ' date_peche ' ] [ 'Y ' ] $_POST [ ' date_peche ' ] [ 'M ' ] . '-' . $_POST [ ' date_peche ' ] [ 'd ' ] ; if ( $_POST [ ' latitude ' ] == '' ) { $_POST [ ' latitude ' ] = ' NULL ' ; <? } if . '-' . ( $_POST [ ' longitude ' ] == '' ) { $_POST [ ' longitude ' ] = ' NULL ' ; } $requete = " INSERT INTO peche VALUES ( DEFAULT ,'" . $_POST [ ' campagne ' ] . " '," . $_POST [ ' ref_peche_campagne ' ] . " ,'" . $date . " ','" . $_POST [ ' saison ' ] . " ','" . $_POST [ ' association ' ] . " ','" . $_POST [ ' localisation ' ] " ',''," . $_POST [ ' latitude ' ] . " ," . $_POST [ ' longitude ' ] . ")" ; $result = pg_query ( $dbconn , $requete ) ; if ( ! $result ) { echo '<b > Erreur de requete </b >< br /> ' ; exit ; } else { echo '<b > Enregistrement ajoute </ b >< br /> ' ; . } echo '<a href =" ' . $_SERVER [ ' PHP_SELF ' ] . '" > Ajouter un autre enregistrement </ a >< br /> ' ; ?> Avec le navigateur Firefox, testez l'ajout de valeurs dans la table Peche en saisissant l'URL suivante : http://localhost/ird/formPeche.php et en remplissant le formulaire. Vériez avec phpPgAdmin que les valeurs saisies ont bien été ajoutées dans la base. 10