Table of Contents
Examinons maintenant comment il est possible d'exploiter ces logiciels
pour fournir aux visiteurs, à la fois un affichage des produits présents
dans notre base de données, et un moyen pour le visiteur d'ajouter un nouveau
produit à cette base. Nous commençons avec un programme PHP qui doit nous
permettre de générer une page HTML, sur laquelle figure un tableau des
produits avec leurs prix correspondants. Nous mettrons ce code dans le
fichier lecture.php
.
Du fait des langages multiples utilisés, il est parfois difficile d'identifier simplement la source d'un dysfonctionnement lors du développement des programmes.
Il est donc conseillé de manière générale, de ne pas faire l'économie des tests d'erreurs. Par exemple, la tentative de connexion à une base devrait prévoir l'échec de la connexion :
@mysql_connect("$hostname", "$username", "$password") or die("Impossible de se connecter a la base");
De même, pour toutes les requêtes MySQL, je conseille de définir une fonction comme celle-ci :
function teste_erreur($query) { $error = mysql_errno(); $error_msg = mysql_error(); if (!empty($error_msg)) { echo "L'erreur $error_msg s'est produite (code=$error)"; echo "pour la requête $query\n"; } }
et de l'appeler systématiquement après une requête mysql_query($q) de façon à ne pas chercher trop longtemps la cause de l'erreur :
$q = " ..... " mysql_query($q); teste_erreur($q);
Supposons que nous ayons une base de données appelée
base
comportant une table appelée
produit
.
Notre première tâche est de demander à PHP de se connecter
à l'ordinateur sur lequel se trouve la base MySQL, puis
de préciser qu'on veut utiliser cette table :
<? mysql_connect("localhost","root","") or die("Impossible de se connecter");; mysql_select_db("base") or die("pas possible de trouver la base");
Ici, nous spécifions que la base est sur l'ordinateur qui exécute le
script PHP (localhost
), et qu'on se connecte
en tant qu'administrateur de la base (root
), qui
n'a pas de mot de passe.
Note | |
---|---|
Si votre base MySQL à été paramétrée différement, changez bien sûr les paramètres (vérifier entre autres que vous n'avez pas besoin d'un mot de passe). |
L'instruction die
permet d'arrêter le script avec un message d'erreur
en cas d'échec.
Demandons maintenant de lister toutes les informations de notre
table produit
. Il faut d'abord, à travers
PHP, faire une requête SQL qui permette de selectionner tous les
champs de la table (première ligne).
$result = mysql_query("SELECT * FROM produit"); $nblignes = mysql_num_rows($result);
Le résultat de cette requête est un tableau de données, comme les deux dernières lignes du tableau suivant :
ref | nom | prix |
---|---|---|
1 | canon bj10e | 120 |
2 | epson stylus 8c | 135 |
Nous devons traiter les lignes du tableau les unes après les
autres. Pour cela, nous avons besoin de connaître le nombre
de ligne de notre tableau. C'est ce qui est fait à la deuxième ligne
de l'extrait de code précédent, et le résultat est conservé dans nblignes
.
Nous sommes maintenant prêt à afficher nos données présentes dans
result
, dans le format HTML.
Nous voulons présenter nos données sous la forme d'une table HTML. Il faut donc faire écrire à PHP, le code HTML correspondant.
La première ligne de la table est constante : il s'agit de l'entête.
Ensuite, il faut extraire, pour chaque ligne de notre tableau,
les valeurs à afficher. Pour cela, nous extrayons pour chaque ligne
i
les valeurs des champs nom et prix de notre table,
avec la commande mysql_result().
Celle-ci prend en argument la table, le numéro de ligne, et le nom de colonne
pour rendre la valeur correspondante dans la table.
Nous mettons les valeurs nom et prix de la table respectivement dans les variables
PHP $prod_nom
et $prod_prix
(le nom de ces variables PHP est tout à fait
arbitraire et n'a pas de relation avec le nom des colonnes SQL).
Quand les valeurs de la ligne ont
été récupérées, nous pouvons écrire la ligne correspondante du tableau HTML.
Enfin, nous fermons la table quand toutes les lignes ont été examinées.
echo "<table><tr><td> Désignation </td><td> Prix </td></tr>\n"; for ($i=0;$i<$nblignes;$i=$i+1) { $prod_nom = mysql_result($result,$i,"nom"); $prod_prix = mysql_result($result,$i,"prix"); echo "<tr><td>$prod_nom</td><td>$prod_prix</td></tr>"; } echo "</table>";
Enfin, il nous faut par prudence refermer la base MySQL mais la quasi-totalité du code PHP nécessaire à la consultation de notre table est écrit.
Nous avons utilisé dans la solution précédente une boucle pour passer en revue chaque ligne de la table de résultat obtenue par la requête SELECT. Le nombre de lignes de la table est donné par mysql_num_rows() et chaque élément est extrait avec mysql_result().
Une alternative un peu plus concise consiste à utiliser
mysql_fetch_array().
Cette fonction prend en argument la table de résultat obtenue par la requête
($result
dans notre exemple), et
renvoie un tableau associatif correspondant à une ligne de la table.
L'indexation du tableau est faite avec les noms des colonnes de la table SQL.
Par exemple, si on récupère un tableau $t
($t = mysql_fetch_array($result)),
et qu'un des champs SQL a pour nom id
, alors on peut
accéder à la valeur de la ligne lue par $t['id']
.
La fonction gère un poineur interne: lors du premier appel, ce sont les éléments
de la première ligne qui sont mis en tableau. Chaque nouvel appel fait progresser
le pointeur pour permettre de lire la ligne suivante.
Un équivalent au bout de code précédent est:
echo "<table><tr><td> Désignation </td><td> Prix </td></tr>\n"; while ($ligne = mysql_fetch_array($result)) { echo "<tr><td>" . $ligne['nom'] . "</td><td>". $ligne['prix']. "</td></tr>"; } echo "</table>";
Récapitulons en listant maintenant le programme complet qui permet
de lire le contenu
de notre table. Donnez une extension php à votre nom de fichier
(lecture.php
par exemple).
<html> <body> <h1> Catalogue produit</h1> <? mysql_connect("localhost","root","") or die("Impossible de se connecter");; mysql_select_db("base") or die("pas possible de trouver la base"); $result = mysql_query("SELECT * FROM produit"); $nblignes = mysql_numrows($result); echo "<table><tr><td>Désignation</td><td>Prix</td></tr>\n"; for ($i=0;$i<$nblignes;$i=$i+1) { $prod_nom = mysql_result($result,$i,"nom"); $prod_prix = mysql_result($result,$i,"prix"); echo "<tr><td>$prod_nom</td><td>$prod_prix</td></tr>"; } echo "</table>"; mysql_close(); ?> </body> </html>
Pour la mise à jour de la base nous avons besoin de deux fichiers : un premier fichier qui doit contenr un formulaire HTML dans lequel l'internaute peut saisir les données à insérer dans la base, et un deuxième fichier (PHP) qui permette de récupérer les données du formulaire pour les insérer dans la base.
Ici, le fichier peut être un simple fichier HTML, puisque toutes les éléments de la page sont statiques.
Nous l'appelons saisie.html
.
Notez que la mise en page HTML est des
plus sommaires, ceci afin d'améliorer la lisibilité et se concentrer
sur les éléments importants du code.
<html> <body> <h1>Mise à jour de la base</h1> <form method="post" action="maj.php"> Référence : <input type="text" name="ref"><br> Nom : <input type="text" name="nom"><br> Prix : <input type="text" name="prix"><br> <input type=submit value="Insérer"> </form> </body> </html>
Il est important de remarquer la partie action
du formulaire. C'est ici qu'on précise quel programme doit
récupérer les données du formulaire et les traiter.
Dans notre cas, il s'agit du fichier maj.php
,
qui sera chargé lorsque le bouton de type submit
sera pressé.
Rappelons que toute cette section ne présente que des éléments connus d'un programmeur HTML. Rien de nouveau !
Nous voulons mainteant récupérer les données du formulaires pour les insérer dans la base. Avant de l'écrire, il est d'abord nécessaire de savoir comment sont transmises les données du formulaire à notre nouveau fichier (celui désigné par l'attribut action dans le formulaire précédent), et comment on peut récupérer ces valeurs en PHP.
Techniquement, le formulaire HTML est posté lorsque l'utilisateur appuie sur le bouton de type submit et que la balise form spécifie method="post". Ceci veut dire qu'une requête HTTP de type POST est émise vers le serveur, et cette requête contient les valeurs du formulaire. La forme sous laquelle sont transmises les valeurs est une suite de couples (variable = valeur).
PHP récupère ces valeurs postées dans un tableau qu'il nomme $_POST.
C'est un tableau associatif, dont les index de tableaux sont les noms des variables
(voir le paragraphe sur les tableaux associatifs en PHP).
Il est donc facile de retrouver la valeur associée à une variable.
Par exemple, $_POST['prix'] désigne la valeur associée au champ HTML prix
dans le formulaire posté.
Tip | |
---|---|
Dans les anciennes configurations de PHP (avant PHP 4.2.0), il n'était pas nécessaire de récupérer explicitement les variables postées.
PHP créait automatiquemlent des variables PHP de même nom que les champs déclarés dans le forumaire HTML.
Ainsi, on récupère la valeur du champ <input type="text" name="prix"> du formulaire dans une variable $prix.
Ce mode aujourd'hui désactivé pour des raisons de sécurité, peut être rétabli
en écrivant register_globals = On dans le fichier |
Maintenant que nous savons récupérer les valeurs des variables du formulaire, il faut les sauvegarder dans la base de données.
Nous écrivons un deuxième fichier, que nous appelons maj.php
.
Voyons le listing de notre fichier.
On retrouve les instructions de connexion à la base, comme dans
the section called “Lecture des données”.
Sur le principe, seule la requête SQL change, avec un
INSERT au lieu d'un select.
<html> <body> <? // connexion à la base mysql_connect("localhost","root","") or die ("Impossible de se connecter"); mysql_select_db("base") or die("Impossible de trouver la base"); // recuperation des valeurs du formulaire $nom = $_POST['nom']; $prix= $_POST['prix']; // insertion des valeurs dans la base $query = "INSERT INTO produit (nom,prix) VALUES ('$nom','$prix')"; $result=mysql_query($query); mysql_close(); ?> Mise a jour faite </body> </html>
Ici, on suppose toujours que ref
est une clé primaire
de la table produit, et qu'elle possède en plus la propriété
autoincrement.
Ainsi, nous n'avons pas à gérer l'unicité de la référence, puisque MySQL
inserera automatiquement une référence entière supérieure aux autres références
trouvées.
La modification de données (on dit encore la mise à jour, ou le remplacement de valeur) peut porter sur une ou plusieurs lignes, d'une ou plusieurs tables. La modification en SQL se dit UPDATE. On indique les noms des colonnes concernées et les valeurs à y mettre (SET col1=valeur1, col2=valeur2, ...) et à quelles lignes cela s'applique (WHERE condition).
Exemple: le nom d'un domaine informatique change de 'fly.com' à 'fly.org'. Je veux mettre à jour la colonne 'nondomaine' de ma table 'adresses' en conséquence. La commande suivante modifiera toutes les lignes qui ont 'fly.com'.
UPDATE adresses SET nomdomaine='fly.org' WHERE nomdomaine='fly.com'
On peut aussi modifier plusieurs colonnes simultanément. Par exemple, modifier dans la table 'adresses' l'email et le pseudo de l'utilisateur numéro 3 (uid=3) se dit:
UPDATE adresses SET email='newemail@fly.org', pseudo='newpseudo' WHERE uid=3
MySQL introduit une extension (ne faisant pas partie du standard SQL) permettant de modifier toute une ligne: REPLACE.
REPLACE INTO table (champ1,champ2,...) WHERE (conditions) VALUES (val1,val2,...);
qui remplace les valeurs présentes dans champ1 par val1, champ2 par val2, etc.
Cette commande est en fait une extension de la comande INSERT. Dans le cas ou l'un des champ est clé primaire de la table, et que la valeur précisée existe déjà dans la table, alors cette ligne sera remplacée. Si aucun enregistrement avec une telle valeur de clé n'existe, alors la ligne sera insérée. Ainsi, cette commande peut être utilisée à des fins d'insertion ou de remplacement.
Reprenons notre exemple précédent.
On veut modifier le prix d'un article dont on connait la référence, stockée dans
la variable $ref.
La référence est la clé primaire (colonne ref
) de notre table
'lecteurs'.
Le remplacement va être opéré si la valeur présente dans $ref existe déjà
dans la table.
$query = "REPLACE INTO produit (ref,marque,modele,annee,prix) VALUES ('$ref','$marque','$modele','$annee','$nouveau_prix')"; $ok = mysql_query( $query ); if ($ok) echo "Le prix de l'article $ref est modifié ...";
Nous n'avons jusqu'ici considéré que la base de données n'était constituée que d'une table. Dans la réalité, la base de données est toujours constituée de plusieurs tables, et il est donc naturel d'aller chercher, pour un élément d'une table, des informations liées présentes dans d'autres tables.
Faire une sélection impliquant plusieurs tables implique un mécanisme plus difficile à comprendre. Une opération sur plusieurs table implique en général de travailler sur le produit cartésien des tables. Une opération fondamentale des bases de données relationnelle est la jointure qui indique comment deux tables doivent être mises en correspondance, et représente donc un sous-ensemeble du produit cartésien.
Une bonne compréhension de ces mécanismes peut être acquise dans des ouvrages traitant spécifiquement des bases de données relationnelles et de SQL. Cependant, l'exemple simple suivant permet de schématiser ce processus.
Dans un forum de discussions, on pourrait avoir par exemple les deux tables suivantes: une table recensant les messages postés avec pour chaque message, le numéro d'utilisateur l'ayant posté. Dans une table profils, on retrouverait toutes les informations sur cet utilisateur.
posts (numpost,user,texte) profils (user,pseudo,email)
Un exemple simplifié de données pour de telles tables pourrait être:
numpost | user | texte |
---|---|---|
1 | 1 | Hello, does anybody knows what is SQL? |
2 | 1 | Hello again, anyone listening? |
3 | 2 | Hello, you'd better buy a book and read it. |
et
user | pseudo | |
---|---|---|
1 | newbie555 | newbie@hotmail.com |
2 | jobasher | jo.basher@gmail.com |
Pour l'affichage des messages, on veut bien sûr pouvoir associer au message
le pseudo ou l'email de l'utilisateur ayant posté le message, ce qui demande
d'aller trouver, à partir de numpost
le pseudo
correspondant. Par exemple, le post 3 (numpost=3
) à été
posté par un utilisateur de pseudo jobasher.
On peut illustrer sur cet exemple simple, la requête SQL qui va nous permettre
d'obtenir le résultat. Etant donné un numéro de post (disons 3), on veut le pseudo
associé tiré de la table profils
:
select pseudo from posts,profils where numpost = 3 and posts.user = profils.user
Tip | |
---|---|
En SQL, un même nom de champ (de colonne) peut être utilisé dans plusieurs
tables. Il devient donc ambigu quand ces tables sont utilisées en même temps.
Pour lever l'ambiguité, il suffit de préfixer le nom du champ
par le nom de sa table. Ici par exemple, on
écrit |
Pour comprendre cette jointure, on peut la représenter par le produit cartésien des deux tables, sur lequel on va imposer des restrictions. Le produit cartésien des deux tables (développant toutes les combinaisons de colonnes des deux tables) donnerait:
numpost | user | texte | user | pseudo | |
---|---|---|---|---|---|
1 | 1 | Hello, does anybody knows what is SQL? | 1 | newbie555 | newbie@hotmail.com |
1 | 1 | Hello, does anybody knows what is SQL? | 2 | jobasher | jo.basher@gmail.com |
2 | 1 | Hello again, anyone listening? | 1 | newbie555 | newbie@hotmail.com |
2 | 1 | Hello again, anyone listening? | 2 | jobasher | jo.basher@gmail.com |
3 | 2 | Hello, you'd better buy a book and read it. | 1 | newbie555 | newbie@hotmail.com |
3 | 2 | Hello, you'd better buy a book and read it. | 2 | jobasher | jo.basher@gmail.com |
La jointure contraint ce résultat en spécifiant l'égalité des valeurs de deux des colonnes.
Ainsi, la seule ligne qui satisfait aux contraintes de notre requête est la dernière du tableau:
numpost=3
et post.user
ainsi que
profils.user
sont égaux (2).
Le résultat à notre requête est donc la table:
pseudo |
---|
jobasher |
Prenons maintenant un autre exemple. Imaginons que notre base est faite de trois tables : les tables clients, produits et commandes.
clients (clid,nom) clé : clid produits(pid,descr,prix) clé : pid commandes(pid,clid,quantite,montant,date) clé : pid,clid
Pour lister les clients qui ont passé des commandes de plus de 2000 Euros et afficher ce qu'ils ont commandé, on peut écrire la requête SQL suivante :
select client.nom,produits.descr from produits,commandes,clients where commandes.montant > 2000 and commandes.pid=produits.pid and commandes.clid=clients.clid
Pour se persuader que la commande select précédente remplit
bien notre objectif, paraphrasons la.
Nous obtiendrons au final une table composée des colonnes
client.nom
et produits.descr
.
Dans la table commandes
seules les lignes dont le
montant dépassent 2000 sont sélectionnées. A chacune de ces lignes
correspond un numéro de client (commandes.clid)
.
Ne seront sélectionnées dans les autres tables que les lignes dont le
numéro de client est égal à celui-ci.