Chapitre 2
Pages Web dynamiques et bases de
données
Une page Web dynamique est générée automatiquement grâce à l’exécution d’un script (PHP
par exemple). C’est le résultat de l’exécution de ce script (code HTML) qui est renvoyé par le
serveur au client. Pour générer ce code HTML, le script peut avoir besoin de données qui sont
stockées en dehors du script, notamment dans des bases de données. Dans ce cas, lors de l’exécution
du script, l’interpréteur PHP interrogera la base de données via des requêtes SQL et utilisera les
informations renvoyées pour générer le code HTML. Le processus de génération de pages Web
dynamiques peut être représenté par la figure 2.1.
2 - Génération de
code HTML
1 - Demande d'exécution
du script PHP
4 - Visualisation
de la page
3 - Envoi du code
HTML généré
Visiteur
Client Serveur
Base de
données
Requête(s)
SQL
Réponse(s)
SQL
Figure 2.1 – Schéma de requête en PHP avec accès à une base de données
Remarque : Lors de l’exécution d’un script, il peut y avoir plusieurs requêtes SQL.
Les bases de données d’un site Web vont pouvoir stocker des informations utiles pour ce site.
La base de données d’un forum va stocker tous les messages postés. Pour un site marchand, la base
de données contiendra la liste des clients/fournisseurs/marchandises. Dans le cas d’un moteur de
recherche, la base contiendra les informations extraites de toutes les pages indexées.
2.1 PHP et bases de données
L’accès aux bases de données dans un script PHP se fait à l’aide de la librairie PHP Data
Objects 1(PDO). Cette librairie implémente une interface entre PHP et n’importe quel système
1. Il existe d’autres moyens d’accéder à une base de données mais qui deviennent obsolètes par rapport à PDO.
27
I.U.T. de Villetaneuse
de gestion de base de données (SGBD) tel que Oracle, MySQL ou PostgreSQL. L’utilisation de la
librairie PDO présente plusieurs avantages :
elle permet d’interroger une base de données quel que soit le SGBD. Le fait de changer de
SGBD nécessite de modifier une seule ligne de code dans le script PHP,
elle facilite l’utilisation des requêtes préparées 2permettant de créer des requêtes plus sé-
curisées.
Les requêtes préparées sont des requêtes SQL qui se déroulent en deux temps. La requête
est tout d’abord préparée par le SGBD, c’est-à-dire analysée et optimisée. La requête est ensuite
exécutée, c’est-à-dire que la base de données est interrogée et les résultats envoyés au script PHP.
Les requêtes préparées peuvent contenir des marqueurs de place (paramètres) dont la valeur est
donnée au moment de l’exécution de la requête.
Les requêtes préparées permettent d’accélérer l’interrogation de la base de données si une
requête préparée est exécutée plusieurs fois (elle ne sera préparée qu’une seule fois). De plus,
l’utilisation des marqueurs de place permet une sécurisation de la base de données en diminuant
le risque d’attaque par injection SQL.
2.1.1 Connexion à la base de données
L’accès à la base de données se fait à travers l’utilisation d’un objet de la classe PDO. La
connexion se fait lors de la construction de cet objet. Le constructeur prend en paramètre 3
valeurs (string) : le DSN, le login et le mot de passe 3.
Le paramètre Data Source Name (DSN) est une chaîne de caractères contenant les informations
requises pour se connecter à la base. Il est constitué du nom du pilote PDO (nom du SGBD), suivi
d’une syntaxe spécifique précisant le serveur où se situe la base de données ainsi que le nom de
cette base.
À titre d’exemple, si la base de données (SGBD MySQL) s’appelle bdCours et se trouve sur le
serveur local, et si les login et mot de passe sont respectivement utilisateur et code, alors la
création de l’objet PDO permettant la connexion à la base se fait selon l’instruction :
 
1$db = new PDO(’mysql:host=localhost;dbname=bdCours’, ’utilisateur’, ’code’);
 
Si la connexion à la base de données échoue, il est clair que le script PHP ne pourra pas
fonctionner correctement puisque les requêtes SQL ne pourront être effectuées. Il faut donc dans
ce cas arrêter le script PHP. Le langage PHP gérant les exceptions, en cas de problème, la connexion
à la base de données lèvera une exception qu’il est préférable d’attraper. Ainsi, la connexion se
fera selon la syntaxe :
 
1try
2{
3$db = new PDO(’mysql:host=localhost;dbname=bdCours’, ’utilisateur’, ’code’);
4}
5catch (PDOException $e)
6{
7// On termine le script en affichant le code de l’erreur ainsi que le message
8die(’<p> La connexion a échoué. Erreur[’.$e->getCode().’] : ’.$e->getMessage().’</p>’);
9}
 
Important : Il faut se connecter une seule fois à la base de données. Il est donc conseiller d’écrire
le code précédent dans un fichier à part, par exemple connexion.php. Chaque script PHP utilisant
la base de données commencera alors par l’instruction require_once(’connexion.php’);. Ceci
permet en plus de marquer vos login et mot de passe uniquement dans le fichier connexion.php
(que vous ne montrez à personne) et non pas dans tous vos scripts PHP.
2. Il existe d’autres méthodes pour interroger la base de données qui ne sont pas décrites dans ce cours.
3. Les deux derniers paramètres sont optionnels.
Mathieu LACROIX
28 Programmation Web 2016/2017
Département informatique
Remarque : Il faut également ajouter juste après l’instanciation de l’objet PDO (dans le bloc
try) les instructions
 
1$bd->query(’SET NAMES utf8’);
2$bd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
La première instruction indique que le script PHP communique avec la base de données en utf-8.
La seconde indique qu’en cas d’erreur, une exception doit être levée.
2.1.2 Interrogation de la base de données
La préparation d’une requête se fait via la méthode prepare de la classe PDO. Cette méthode
prend en paramètre une requête SQL (sous la forme d’une chaîne de caractères) et retourne un
objet de la classe PDOStatement correspondant à la requête optimisée. En cas d’erreur lors de la
préparation, une exception PDOException est levée.
La requête est ensuite exécutée grâce à la méthode execute de la classe PDOStatement. Elle
s’applique à l’objet retourné par la méthode prepare. En cas d’erreur, une exception est également
levée.
La récupération de la réponse d’une requête se fait via la méthode fetch. Celle-ci retourne
ligne suivante du résultat de la requête, ou false en cas d’erreur. Le type retourné dépend de la
valeur passée en paramètre de la méthode fetch :
PDO::FETCH_ASSOC : la valeur retournée est un tableau associatif. Les clés sont les noms
des colonnes dans la requête et les valeurs celles de la ligne.
PDO::FETCH_NUM : les clés associées aux valeurs sont les indices des colonnes de la requête.
PDO::FETCH_BOTH : le tableau retourné contient deux fois chaque valeur. Les clés sont les
noms et les indices des colonnes de la requête (le tableau correspond à l’union des deux
premiers tableaux). C’est la valeur par défaut.
PDO::FETCH_OBJ : la valeur retournée est cette fois-ci un objet. Les noms des attributs sont
les noms de colonnes de la requête, les valeurs de ces attributs étant les valeurs de la ligne.
Voici un exemple d’interrogation d’une base de données. Supposons que l’on ait la table
Personnes contenant les lignes suivantes.
Nom Prenom
Grappe Roland
David Julien
Borne Sylvie
Toulouse Sophie
L’exécution du code
 
1try
2{
3$requete = $bd->prepare(’SELECT Nom, Prenom FROM Personnes’);
4$requete->execute();
5$tab = $requete->fetch(PDO::FETCH_ASSOC);
6echo ’<p> Nom : ’ . $tab[’Nom’] . ’ et prénom : ’ . $tab[’Prenom’] .’</p>’;
7$tab = $requete->fetch(PDO::FETCH_NUM);
8echo ’<p> Nom : ’ . $tab[0] . ’ et prénom : ’ . $tab[1].’</p>’;
9$tab = $requete->fetch(PDO::FETCH_BOTH);
10 echo ’<p> Nom : ’ . $tab[0] . ’ et prénom : ’ . $tab[’Prenom’].’</p>’;
11 $obj = $requete->fetch(PDO::FETCH_OBJ);
12 echo ’<p> Nom : ’ . $obj->Nom . ’ et prénom : ’ . $obj->Prenom.’</p>’;
13 }
14 catch(PDOException $e)
15 {
Programmation Web 2016/2017
29 Mathieu LACROIX
I.U.T. de Villetaneuse
16 die(’<p> Erreur[’.$e->getCode().’] : ’.$e->getMessage().’</p>’);
17 }
 
affichera alors
 
1Nom : Grappe et prénom : Roland
2Nom : David et prénom : Julien
3Nom : Borne et prénom : Sylvie
4Nom : Toulouse et prénom : Sophie
 
Lors du premier appel, fetch retourne le tableau correspondant à la première ligne de la table
Personnes. Comme la valeur PDO::FETCH_ASSOC est passée en argument, le tableau retourné est
 
1Array
2(
3[Nom] => Grappe
4[Prenom] => Roland
5)
 
Lors du deuxième appel, fetch retourne les informations correspondant à la deuxième ligne de la
table car à chaque appel, fetch passe automatiquement à la ligne suivante. Comme PDO::FETCH_NUM
est passé en paramètre, la valeur retournée est
 
1Array
2(
3[0] => David
4[1] => Julien
5)
 
Le tableau retourné par le troisième appel est
 
1Array
2(
3[Nom] => Borne
4[0] => Borne
5[Prenom] => Sylvie
6[1] => Sylvie
7)
 
Lors du 4ème appel, l’objet retourné contient deux attributs Nom et Prenom dont les valeurs sont
respectivement Toulouse et Sophie.
Pour chaque ligne de la réponse d’une requête SQL, il faut appeler la méthode fetch. Il faut
donc utiliser une boucle pour récupérer toutes les lignes. Pour cela, on utilise le fait que la méthode
fetch retourne false en cas d’erreur, notamment s’il n’y a plus de ligne.
L’affichage de toutes les personnes de la table se fait de la manière suivante :
 
1$requete = $bd->prepare(’SELECT Nom, Prenom FROM Personnes’);
2$requete->execute();
3while($ligne = $requete->fetch(PDO::FETCH_ASSOC))
4{
5echo ’<p> Nom : ’ . $ligne[’Nom’] . ’ et prénom : ’ . $ligne[’Prenom’] . ’</p>’;
6}
 
Remarque : Le nombre d’appels de fetch correspond au nombre de lignes de la réponse + 1
(pour le false).
ISur ce thème : Exercice 1
Mathieu LACROIX
30 Programmation Web 2016/2017
Département informatique
2.1.3 Marqueurs de place
Les marqueurs de place permettent de marquer des endroits dans la requête SQL qui seront
remplacés par des valeurs au moment de l’exécution de cette requête. Les marqueurs permettent
donc d’exécuter plusieurs fois une même requête avec des valeurs de marqueurs différentes. De
plus, lorsque les marqueurs sont utilisés pour insérer dans la requête SQL des valeurs saisies par
l’utilisateur, ils permettent de sécuriser la base de données des attaques par injection SQL.
Dans une requête SQL, un marqueur de place a un nom précédé du symbole ":". Avant
l’exécution de la requête, il faudra alors donner une valeur à tous les marqueurs de place contenus
dans la requête, grâce à la méthode bindValue. Cette méthode prend en paramètre un nom de
marqueur et sa valeur 4.
Voici un exemple de requête préparée avec des marqueurs de place 5:
 
1$couleur = ’rouge’;
2$req = $bd->prepare(’SELECT nom, couleur, calories
3FROM fruit
4WHERE calories < :calories AND couleur = :couleur’);
5$req->bindValue(’:calories’, 150);
6$req->bindValue(’:couleur’, $couleur);
7$req->execute();
 
Lors de l’exécution, les marqueurs ’:calories’ et ’:couleur’ sont respectivement remplacés
par les valeurs 150 et rouge. La requête est donc :
SELECT nom, couleur, calories FROM fruit WHERE calories < 150 AND couleur=’rouge’
ISur ce thème : Exercice 2
2.2 Sécurité
Il existe plusieurs failles de sécurité importantes au niveau de la programmation d’un site Web.
Il est extrêmement important de contrer ces failles pour sécuriser son site Web. Bien que ce ne
soit pas les seules, elles font partie des failles couramment utilisées pour pirater des sites Web ou
les bases de données de ces sites.
2.2.1 Attaque par injection SQL
Ce type d’attaque consiste à modifier une requête SQL pour obtenir un résultat différent de
celui prévu. Supposons que l’on ait une table Commandes dans la base de données contenant les
commandes de chaque client. Cette table pourrait être du type 6:
Id IdC NomP Qte
1 1 Canapé 1
2 1 Lit 2
3 2 Table 1
4 2 Voiture 1
Le champ Id correspond à la clé primaire, IdC est l’identifiant du client (clé étrangère), et NomP
et Qte désignent respectivement le nom du produit et la quantité demandée.
Pour afficher la liste des commandes d’un utilisateur, on pourrait être tenté d’écrire le code
PHP suivant :
4. La méthode bindValue peut également prendre un troisième paramètre indiquant le type de la valeur
(PDO::PARAM_INT,PDO::PARAM_STR, etc). Ce paramètre est parfois nécessaire pour construire des requêtes syntaxi-
quement correctes (notamment avec la clause LIMIT).
5. Exemple issu du site PHP.net
6. Cette table est simpliste mais suffisante pour montrer la faille de sécurité.
Programmation Web 2016/2017
31 Mathieu LACROIX
1 / 10 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !