Accueil | MEET | PFEG | IGC | STG | BTS IG | BTS SIO | Cours | Didactique | Exos | Glossaire | Labo | Sujets | Outils Imprimer cette page



Rechercher
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

5. Accéder à une base de données

a. Introduction

L'interaction entre une page HTML et une base de données fait collaborer deux technologies : CGI et SQL intégrées dans un langage hôte (il y a bien entendu d'autres solutions).

Le schéma de principe de l'application devient donc le suivant (nous sommes en plein dans l'architecture client/serveur !) :

1. Le navigateur indique l'URL http://www.monSite.monProgCgi. Ce lien désigne le programme cgi sur le serveur (selon les langages, il s'agit d'un script ou d'un exécutable).

2. Le serveur http (Apache par exemple) lance l'exécution du programme.

3. Le programme cgi s'exécute et envoie une requête SQL au SGBD.

4. Le SGBD exécute la requête reçue et transmet le résultat au programme cgi.

5. Le programme cgi reçoit le résultat de la requête et construit une page html à la volée. Cette page est retournée au serveur http.

6. Le serveur http transmet la page construite précédemment au navigateur. Celui-ci reçoit donc du texte html comme d'habitude. Il l'interprète et affiche le résultat.

Base de données exemple

Nous travaillerons avec une base de données très simple dont voici le schéma :

service (code (char 3), designation (char 30))

employe (matricule (char 4), nom (char 25), prenom (char 20), cadre (char 1), service# (char 3))

Cette base est implantée sous postgresql.

Un programme source porte l'extension .pgc. Il est précompilé à l'aide de la commande :

ecpg -I /usr/include/pgsql/ -o monProg.cpp monProg.pgc

Le programme exécutable est ensuite produit à partir du source c++ obtenu par :

g++ -g -I /usr/include/pgsql -o monProg monProg.cpp /usr/lib/cgic.o -lecpg -lpq -lcrypt

b. Affichage des données de la base

Pour afficher des données issues de la base, il faut créer une page HTML dynamique affichant le résultat de l'exécution d'une requête. Le programme cgi suivant affiche la liste des employés.

// cgi07.pgc
#define _XOPEN_SOURCE // ces deux lignes concernent postgreSql
#include <unistd.h>
#include <iostream.h>
#include <cgic.h>
exec sql include sqlca;
int cgiMain() {

// déclarations et connexion à la base (le niveau de sécurité est fonction du paramétrage du SGBD)
exec sql begin declare section;

char hMatricule[5];
char hNom[26];
char hPrenom[21];
char hCadre;
char hService[4];

exec sql end declare section;
exec sql declare listeEmployes cursor for

select matricule,nom,prenom,cadre,service from employe;

exec sql connect to 'administrateur' user 'administrateur';
cgiHeaderContentType("text/html");
cout << "<head>";
cout << "<title> Liste des employés </title>";
cout << "</head>";
cout << "<body>";
exec sql open listeEmployes;
exec sql fetch from listeEmployes into :hMatricule,:hNom,:hPrenom,:hCadre,:hService;
while (sqlca.sqlcode==0) {

cout << hMatricule << ' ';
cout << hNom << ' ';
cout << hPrenom << ' ';
cout << hCadre << ' ';
cout << hService << "<br>";
exec sql fetch from listeEmployes into

:hMatricule,:hNom,:hPrenom,:hCadre,:hService;

}
exec sql close listeEmployes;
cout << "</body>";
cout << "</html>";
exec sql disconnect;
return 0;

}

Après la connexion à la base de données, le programme construit "à la volée" la page html contenant les informations lues à l'aide du curseur.

Ce programme produit le résultat suivant :

c. Mise en forme des données

Il est bien entendu possible de faire un petit effort de présentation. Le programme cgi08 affiche la liste des employés (nom et prénom) dans un tableau formaté en HTML.

La méthode la plus simple est sans doute de commencer par écrire une page html affichant le type de résultat souhaité (à l'aide d'un éditeur ou d'un générateur).

Cette page ...

... est obtenue par le source HTML ci-dessous :

<HTML>
<HEAD>
<TITLE> Liste des employés </TITLE>
</HEAD>
<BODY>
<H1>Liste nominative des employés</H1>
<P><TABLE BORDER=2 WIDTH="75%">
<TR><TH>NOM</TH><TH>PRENOM</TH></TR>
<TR><TD>Loisel</TD><TD>Pierre</TD></TR>
<TR><TD>Durand</TD><TD>Paul</TD></TR>
<TR><TD>Fauvel</TD><TD>Nicole</TD></TR>
</TABLE>
<P>
Il y a 3 employés.
</BODY>
</HTML>

Ce source HTML peut être généré par le programme suivant :

// cgi08.pgc

#define _XOPEN_SOURCE
#include <unistd.h>
#include <iostream.h>
#include <cgic.h>
exec sql include sqlca;
int cgiMain() {

exec sql begin declare section;
char hNom[26];
char hPrenom[21];
exec sql end declare section;
exec sql declare listeEmployes cursor for
select nom,prenom from employe;
exec sql connect to 'administrateur' user 'administrateur';
int nbEmployes;
cgiHeaderContentType("text/html");
cout << "<head>";
cout << "<title> Liste des employés </title>";
cout << "</head>";
cout << "<body>";
cout << "<h1>Liste nominative des employés</h1>";
cout << "<p><table border=2 width=\"75%\">";
cout << "<tr><th>NOM</th><th>PRENOM</th></tr>";
nbEmployes=0;
exec sql open listeEmployes;
exec sql fetch from listeEmployes into :hNom,:hPrenom;
while (sqlca.sqlcode==0) {

nbEmployes++;
cout << "<tr><td>" << hNom << "</td><td>" << hPrenom << "</td></tr>";
exec sql fetch from listeEmployes into :hNom,:hPrenom;

}
exec sql close listeEmployes;
cout << "</table>";
cout << "<p>Il y a " << nbEmployes << " employés.";
cout << "</body>";
cout << "</html>";
exec sql disconnect;
return 0;

}

d. Sélection de données

Un premier programme cgi affiche la liste des services. L'utilisateur sélectionne le service souhaité et un second programme recherche et affiche les employés de ce service.

Interface souhaitée pour la sélection du service :

Le code HTML correspondant à cette page est le suivant :

<HTML>
<HEAD>
<TITLE>Sélection du service</TITLE>
</HEAD>
<BODY>
<FORM action="/cgi-bin/cgi10" method="POST">
<H2>Liste des employés par service</H2>
<P>Sélectionnez le service souhaité :</P>
<SELECT NAME="service" SIZE=5>
<OPTION SELECTED value = "s04">s04 administration
<OPTION value = "s03">s03 commercial
<OPTION value = "s02">s02 emballage
<OPTION value = "s01">s01 fabrication
</SELECT>
<P><INPUT TYPE="submit" VALUE="Afficher la liste"></P>
</FORM>
</BODY>

</HTML>

L'attribut value dans les balises option va permettre de faciliter la recherche des employés dans la base de données. Cette recherche se fera dans le programme cgi10 cité dans l'attribut action du formulaire.

Il reste à écrire le programme cgi09 permettant de le générer à partir de la base de données :

// cgi09.pgc

#define _XOPEN_SOURCE
#include <unistd.h>
#include <iostream.h>
#include <cgic.h>
exec sql include sqlca;
int cgiMain() {

exec sql begin declare section;
char hCode[4];
char hDesignation[31];
exec sql end declare section;
exec sql declare listeServices cursor for

select code,designation from service order by designation;

exec sql connect to 'administrateur' user 'administrateur';
cgiHeaderContentType("text/html");
cout << "<head>";
cout << "<title> Sélection du service </title>";
cout << "</head>";
cout << "<body>";
cout << "<form action=\"/cgi-bin/cgi10\" method=post>";
cout << "<h2>Liste des employés par service</h2>";
cout << "<p>Sélectionnez le service souhaité :</p>";
cout << "<select name=\"service\" size=5>";
exec sql open listeServices;
exec sql fetch from listeServices into :hCode,:hDesignation;
if (sqlca.sqlcode==0) {

cout << "<option selected value = \"" << hCode << "\">" << hCode << ' ' << hDesignation;
exec sql fetch from listeServices into :hCode,:hDesignation;
while (sqlca.sqlcode==0) {

cout << "<option value = \"" << hCode << "\">" << hCode << ' ' << hDesignation;
exec sql fetch from listeServices into :hCode,:hDesignation;

}

}
exec sql close listeServices;
cout << "</select>";
cout << "<p><input type=\"submit\" value = \"Afficher la liste\"></p>";
cout << "</form>";
cout << "</body>";
cout << "</html>";
exec sql disconnect;
return 0;

}

Le programme cgi10, appelé depuis ce formulaire, va rechercher les employés du service sélectionné et les afficher dans un tableau HTML.

// cgi10.pgc
#define _XOPEN_SOURCE
#include <unistd.h>
#include <iostream.h>
#include <cgic.h>
exec sql include sqlca;
int cgiMain() {

exec sql begin declare section;
char hNom[26];
char hPrenom[21];
char hCode[4];
exec sql end declare section;
exec sql declare listeEmployes cursor for

select nom,prenom from employe where service = :hCode;

exec sql connect to 'administrateur' user 'administrateur';
cgiFormString("service",hCode,4);
int nbEmployes;
cgiHeaderContentType("text/html");
cout << "<head><title> Liste des employés </title></head>";
cout << "<body>";
cout << "<h1>Service " << hCode << " :</h1>";
cout << "<p><table border=2 width=\"75%\">";
cout << "<tr><th>NOM</th><th>PRENOM</th></tr>";
nbEmployes=0;
exec sql open listeEmployes;
exec sql fetch from listeEmployes into :hNom,:hPrenom;
while (sqlca.sqlcode==0) {

nbEmployes++;
cout << "<tr><td>" << hNom << "</td><td>" << hPrenom << "</td></tr>";
exec sql fetch from listeEmployes into :hNom,:hPrenom;

}
exec sql close listeEmployes;
cout << "</table>";
cout << "<p>Il y a " << nbEmployes << " employés.";
cout << "</body>"; cout << "</html>";
exec sql disconnect;
return 0;

}

e. Mise à jour des données

Le formulaire ci-dessous permet la saisie des informations concernant un nouvel employé.

Lorsque l'utilisateur clique sur le bouton enregistrer, le programme cgi12 est lancé.

Ce formulaire est généré par le programme cgi11.

// cgi11.pgc
#include <iostream.h>
#include <cgic.h>
exec sql include sqlca;
int cgiMain() {

exec sql begin declare section;
char hCode[4];
char hDesignation[31];
exec sql end declare section;
exec sql declare listeServices cursor for

select code,designation from service order by designation;

exec sql connect to 'administrateur' user 'administrateur';
cgiHeaderContentType("text/html");
cout << "<head>";
cout << "<title> Saisie </title>";
cout << "</head>";
cout << "<body>";
cout << "<form action=\"/cgi-bin/cgi12\" method=post>";
cout << "<h2>Saisie d'un employé</h2>";
cout << "Matricule : <input type=\"text\" name=\"matricule\" size=3><br>";
cout << "Nom : <input type=\"text\" name=\"nom\" size=25><br>";
cout << "Prénom : <input type=\"text\" name=\"prenom\" size=20><br>";
cout << "Cadre <input type=\"checkbox\" name=\"cadre\"><br>";
cout << "Service :<br>";
cout << "<select name=\"service\" size=5>";
exec sql open listeServices;
exec sql fetch from listeServices into :hCode,:hDesignation;
if (sqlca.sqlcode==0) {

cout << "<option selected value = \"" << hCode << "\">" << hCode << ' ' << hDesignation;
exec sql fetch from listeServices into :hCode,:hDesignation;
while (sqlca.sqlcode==0) {

cout << "<option value = \"" << hCode << "\">" << hCode << ' ' << hDesignation;
exec sql fetch from listeServices into :hCode,:hDesignation;

}

}
exec sql close listeServices;
cout << "</select>";
cout << "<p><input type=\"submit\" value = \"Enregistrer\"> <input type=\"reset\"
value=\"Annuler\"></p>";
cout << "</form>";
cout << "</body>";
cout << "</html>";
exec sql disconnect;
return 0;

}

Le programme cgi12, lancé depuis le formulaire précédent, permet l'insertion du nouvel employé dans la base de données. Un message d'erreur est affiché en cas de problème (clé primaire dupliquée par exemple).

// cgi12.pgc
#define _XOPEN_SOURCE
#include <unistd.h>
#include <iostream.h>
#include <chaine.h>
#include <cgic.h>
exec sql include sqlca;
int cgiMain() {

exec sql begin declare section;
char hMatricule[5];
char hNom[26];
char hPrenom[21];
char hService[4];
exec sql end declare section;
exec sql connect to 'administrateur' user 'administrateur';
chaine valeurCadre;
cgiFormString("matricule",hMatricule,5);
cgiFormString("nom",hNom,26);
cgiFormString("prenom",hPrenom,21);
cgiFormString("cadre",cv_chainec(valeurCadre),3);
cgiFormString("service",hService,4);
cgiHeaderContentType("text/html");
cout << "<head>";
cout << "<title> Ajout d'un employé </title>";
cout << "</head>";
cout << "<body>";
if (valeurCadre=="on")

exec sql insert into employe values ( :hMatricule, :hNom, :hPrenom, 'o', :hService );

else

exec sql insert into employe values ( :hMatricule, :hNom, :hPrenom, 'n', :hService );

if (sqlca.sqlcode==0) {

exec sql commit;
cout << "L'employé a été correctement ajouté";
}

else

cout << "Attention, l'ajout de l'employé a échoué !!!";

cout << "</body>";
cout << "</html>";
exec sql disconnect;
return 0;

}

Il est bien entendu possible d'utiliser toute la puissance du langage SQL : delete, update, create...

   

_____________________________________________  
© - Réseau C E R T A 

Ministère de l'Éducation Nationale