Technologies du WebPHP
Bases de données
Par Elena CABRIO
Basé sur les cours de Jean-Pierre Lozi, Philippe Renevier et Andrea Tettamanzi
8/04/2020 Technologies du Web – ELENA CABRIO
Introduction
Pour enregistrer des données, on a appris jusqu'à là a:
affecter des valeur a des variables (mais elles restent en mémoire
seulement le temps de la génération de la page)
écrire dans des fichiers (mais cela devient vite très compliqué dès que
vous avez beaucoup de données à enregistrer)
Une base de données (BDD) permet d'enregistrer des données de façon
organisée et hiérarchisée.
Il s’agit d’ un système qui enregistre des informations classées.
8/04/2020 Technologies du Web – ELENA CABRIO
Systèmes de Gestion de Bases de
Données
Les SGBD sont les programmes qui se chargent du stockage des données. Parmi les plus connus:
MySQL : libre et gratuit (probablement le SGBD le plus connu)
PostgreSQL : libre et gratuit, avec plus de fonctionnalités de MySQL mais un peu moins connu ;
SQLite: libre et gratuit, très léger mais très limité en fonctionnalités ;
Oracle : utilisé par les très grosses entreprises: un des SGBD les plus complets, mais payante ;
Microsoft SQL Server : le SGBD de Microsoft.
8/04/2020 Technologies du Web – ELENA CABRIO
Langage SQL
Langage SQL pour “communiquer” avec le SGBD
Langage standard
PHP fait la jonction entre le serveur et MySQL
1
23
4
client serveur
8/04/2020 Technologies du Web – ELENA CABRIO
Structure d'une base de données
ID nom possesseur console
1 Super Mario Bros Florent NES
2 Sonic Patrick Megadrive
3Zelda : ocarina of
timeFlorent Nintendo 64
4 Mario Kart 64 Florent Nintendo 64
Une table est donc représentée sous la forme d'un tableau ;
Voici à quoi peut ressembler le contenu d'une table appellee «jeux-video».
Les champs dans cet exemple sont : «nom», «possesseur», «console».
Chaque ligne est une entrée.
8/04/2020 Technologies du Web – ELENA CABRIO
Organisation d’une BDD MySQL
8/04/2020 Technologies du Web – ELENA CABRIO
PhpMyAdmin
- phpMyAdmin est un outil qui nous permet de visualiser
rapidement l'état de notre base de données ainsi que de la
modifier, sans avoir à écrire de requêtes SQL.
- On crée généralement un champ nommé id qui sert à
numéroter les entrées d'une table. Ce champ doit avoir un
index PRIMARY (on dit qu'on crée une clé primaire) et
l'option AUTO_INCREMENT qui permet de laisser MySQL
gérer la numérotation.
8/04/2020 Technologies du Web – ELENA CABRIO
PhpMyAdmin
- MySQL gère différents types de données pour ses champs, à
la manière de PHP. On trouve des types adaptés au stockage
de nombres, de textes, de dates, etc.
- phpMyAdmin possède un outil d'importation et d'exportation
des tables qui nous permettra notamment d'envoyer notre
base de données sur Internet lorsque on met notre site en
ligne.
- Savoir manipuler phpMyAdmin permet de vérifier si les
manipulations qu’on fait en PHP ont bien l'impact que nous
attendons dans notre base de données
8/04/2020 Technologies du Web – ELENA CABRIO
Lire les données
Pour pouvoir travailler avec la base de données en PHP, il faut d'abord s'y connecter.
PHP propose plusieurs moyens de se connecter à unebase de données MySQL:
L'extension mysql_ : ce sont des fonctions qui permettentd'accéder à une base de données MySQL et donc de communiquer avec MySQL. Leur nom commence toujoursparmysql_
L'extension mysqli_ : ce sont des fonctions amélioréesd'accès à MySQL. Elles proposent plus de fonctionnalitéset sont plus à jour.
L'extension PDO : c'est un outil complet qui permetd'accéder à n'importe quel type de base de données.
8/04/2020 Technologies du Web – ELENA CABRIO
La déclaration des variables
Les variables qui permettent la connexion à la base de
données (paramètres des fonctions de connexion à la base) sont :
$user : Le nom d'utilisateur
$passwd : Le mot de passe
$host : L'hôte (ordinateur sur lequel le SGBD est installé)
$bdd : Le nom de la base de données
8/04/2020 Technologies du Web – ELENA CABRIO
La déclaration des variables
Les variables ne sont pas visibles par vos visiteurs étant
donné que le script (.php) est systématiquement interprété
par le serveur Web
Il est possible de:
passer les valeurs de ces variables directement dans
chaque fonction permettant la connexion (mais ca peut
devenir gênant…)
stocker ces valeurs dans un fichier à part, afin de changer
les valeurs dans tous les fichiers y faisant référence en
une seule fois
8/04/2020 Technologies du Web – ELENA CABRIO
Fonctions de base
PHP fournit un grand choix de fonctions permettant de manipuler
les bases de données
Quatre fonctions sont essentielles :
La fonction de connexion au serveur
La fonction de choix de la base de données
La fonction de requête
La fonction de déconnexion
8/04/2020 Technologies du Web – ELENA CABRIO
Connexion au serveur
Avec le SGBD MySQL, la fonction qui ouvre ou réutilise une connexion à un serveur
MySQL est mysqli_connect
<?php
$link = mysqli_connect("localhost", "mysql_user", "mysql_password")
or die("Impossible de se connecter : " . mysql_error());
echo 'Connexion réussie';
mysqli_close($link);
?>
resource mysqli_connect ([ string $server = ini_get("mysql.default_host") [, string
$username = ini_get("mysql.default_user") [, string $password =
ini_get("mysql.default_password") [, bool $new_link = false [, int $client_flags = 0 ]]]]] )
8/04/2020 Technologies du Web – ELENA CABRIO
Choix de la base de données
Avec le SGBD MySQL, la fonction qui permet de sélectionner une base de
données sur le serveur associée est mysqli_select_db (avec le parametre
$link_identifier)
bool mysqli_select_db ( string $database_name [, resource $link_identifier = NULL ] )
<?php
$link = mysqli_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {die('Impossible de se connecter : ' . mysqli_error());}
// Rendre la base de données foo, la base courante
$db_selected = mysqli_select_db('foo', $link);
if (!$db_selected) {
die ('Impossible de sélectionner la base de données : ' . mysqli_error());
}
?>8/04/2020 Technologies du Web – ELENA CABRIO
Requête
Avec le SGBD MySQL, la fonction qui renvoie une requête a un
serveur MySQL est mysql_query
mixed mysqli_query ( string $query [, resource $link_identifier = NULL ] )
- Pour les requêtes du type SELECT, SHOW, DESCRIBE, EXPLAIN
et les autres requêtes retournant un jeu de résultats,
mysqli_query() retournera une ressource en cas de succès,
ou FALSE en cas d'erreur.
- Pour les autres types de requêtes, INSERT, UPDATE, DELETE,
DROP, etc., mysqli_query() retourne TRUE en cas de succès ou
FALSE en cas d'erreur. 8/04/2020 Technologies du Web – ELENA CABRIO
Déconnexion
Avec le SGBD MySQL, la fonction pour fermer un connexion
MySQL est mysql_close
bool mysqli_close ([ resource $link_identifier = NULL ] )
<?php
$link = mysqli_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
die('Connexion impossible : ' . mysqli_error());
}
echo 'Connexion réussie';
mysqli_close($link);
?>8/04/2020 Technologies du Web – ELENA CABRIO
Gestion des erreurs
Certaines de ces fonctions renvoient une valeur permettant de connaître
l'état de la connexion, ainsi il est possible d'interrompre le script afin
d'éviter les erreurs en cascade.
Deux méthodes permettent d'effectuer cette opération : Le stockage du résultat de l'exécution de la fonction dans une variable.
$connect = mysqli_connect($host,$user,$passwd);
L'utilisation de la fonction die() en cas d'erreur d'exécution. Si la fonction
retourne la valeur 0 (c'est-à-dire s'il y a une erreur) la fonction die renvoie un
message d'erreur.
mysqli_connect($host,$user,$passwd) or die("erreur de connexion
au serveur $host"); 8/04/2020 Technologies du Web – ELENA CABRIO
Traitement des résultats
Lorsque l'on effectue une requête de selection de tuple à l'aide de la fonction
mysqli_query, il est essentiel de stocker le résultat de la requête (les
enregistrements) dans une variable, que l'on nomme généralement $result.
Cette variable contient l'ensemble des enregistrements et n'est donc pas
exploitable telle quelle.
On utilise la fonction mysqli_fetch_row(), qui découpe les lignes de résultat en
colonnes (par exemple Nom,adresse,...) et les affecte à une variable tableau dans
l'ordre où elles arrivent.
8/04/2020 Technologies du Web – ELENA CABRIO
mysql_fetch_row()
Retourne un tableau numérique de chaînes qui correspond à la ligne
récupérée, ou FALSE s'il n'y a plus de lignes.
Voir http://php.net/manual/fr/function.mysqli-fetch-row.php
array mysqli_fetch_row ( resource $result )
<?php
$result = mysqli_query("SELECT id,email FROM people WHERE id = '42'");
if (!$result) {
echo 'Impossible d\'exécuter la requête : ' . mysqli_error();
exit;
}
$row = mysqli_fetch_row($result);
echo $row[0]; // 42
echo $row[1]; // la valeur du champ email
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Détecter un résultat nulIl peut être utile, avant d'insérer des données dans une table, de détecter la
présence d'un enregistrement dans une table, afin d'éviter de stocker des
doublons.
Cela peut se faire en effectuant une requete SQL avec un ordre SELECT et
une clause WHERE permettant de vérifier la présence ou non
d'enregistrements correspondant à la requête.
La non présence de résultat se traduit par un retour nul de la part de la
fonction mysqli_fetch_row().
if ( ! mysqli_fetch_row($result)) {
echo "Aucun enregitrement ne correspond\n";
}8/04/2020 Technologies du Web – ELENA CABRIO
Interroger une table MySQL: an exempleRequête SQL : CREATE TABLE famille_tbl ( id int(11) NOT NULL auto_increment, nom varchar(255)
NOT NULL, prenom varchar(255) NOT NULL, statut varchar(255) NOT NULL, date date DEFAULT '0000-
00-00' NOT NULL, PRIMARY KEY (id), KEY id (id), UNIQUE id_2 (id) );
INSERT INTO famille_tbl VALUES( '', 'Dupond', 'Grégoire', 'Grand-père', '1932-05-17');
INSERT INTO famille_tbl VALUES( '', 'Dupond', 'Germaine', 'Grand-mère', '1939-02-15');
INSERT INTO famille_tbl VALUES( '', 'Dupond', 'Gérard', 'Père', '1959-12-22');
INSERT INTO famille_tbl VALUES( '', 'Dupond', 'Marie', 'Mère', '1961-03-02');
INSERT INTO famille_tbl VALUES( '', 'Dupond', 'Julien', 'Fils', '1985-05-17');
INSERT INTO famille_tbl VALUES( '', 'Dupond', 'Manon', 'Fille', '1990-11-29');
Contenu de la table "famille_tbl"
id nom prenom statut date
1 Dupond Grégoire Grand-père 1932-05-17
2 Dupond Germaine Grand-mère 1939-02-15
3 Dupond Gérard Père 1959-12-22
4 Dupond Marie Mère 1961-03-02
5 Dupond Julien Fils 1985-05-17
6 Dupond Manon Fille 1990-11-29
8/04/2020 Technologies du Web – ELENA CABRIO
Interroger une table MySQL: an exemple
<?php
// on se connecte à MySQL
$db = mysqli_connect('localhost', 'login', 'password');
// on sélectionne la base
mysqli_select_db('nom_de_la_base',$db);
// on crée la requête SQL
$sql = 'SELECT nom,prenom,statut,date FROM famille_tbl';
// on envoie la requête
$req = mysqli_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.
mysqli_error());
// on fait une boucle qui va faire un tour pour chaque enregistrement
while($data = mysqli_fetch_assoc($req))
{
// on affiche les informations de l'enregistrement en cours
echo '<b>'.$data['nom'].' '.$data['prenom'].'</b> ('.$data['statut'].')';
echo ' <i>date de naissance : '.$data['date'].'</i><br>';
}
// on ferme la connexion à mysql
mysqli_close();
?>
Dupond Grégoire (Grand-
père),
date de naissance : 1932-05-
17
Dupond Germaine (Grand-
mère),
date de naissance : 1939-02-
15
Dupond Gérard (Père), date
de naissance : 1959-12-22
Dupond Marie (Mère), date de
naissance : 1961-03-02
Dupond Julien (Fils), date de
naissance : 1985-05-17
Dupond Manon (Fille), date de
naissance : 1990-11-29
8/04/2020 Technologies du Web – ELENA CABRIO
Interroger une table MySQL: an exemple
Affichage des résultats par ordre alphabétique de prénom.
<?php
// Gardez le code ci-dessus, changez juste la requête SQL !
$sql = 'SELECT nom,prenom,statut,date FROM famille_tbl ORDER BY prenom';
// L'opérateur ORDER BY permet de classer soit alphabétiquement
// soit numériquement suivant le type du champ.
// Si l'on souhaite classer en décroissant (ex. de Z à A), nous
// y ajouterons DESC soit : ORDER BY prenom DESC
?>
Dupond Gérard (Père), date
de naissance : 1959-12-22
Dupond Germaine (Grand-
mère), date de naissance :
1939-02-15
Dupond Grégoire (Grand-
père), date de naissance :
1932-05-17
Dupond Julien (Fils), date de
naissance : 1985-05-17
Dupond Manon (Fille), date de
naissance : 1990-11-29
Dupond Marie (Mère), date de
naissance : 1961-03-02
8/04/2020 Technologies du Web – ELENA CABRIO
Interroger une table MySQL: an exemple
Affichage des résultats par comparison de date.
<?php
// Gardez le code ci-dessus, changez juste la requête SQL !
$sql = "SELECT nom,prenom,statut FROM famille_tbl WHERE date<'1960-01-01'";
// L'avantage d'avoir un type DATE dans notre base de données, c'est que nous pouvons
//comparer des dates dans la requête SQL.
// Ici nous ne souhaitons afficher que les membres de la
//famille qui sont nés avant le 1er janvier 1960, soit :
//WHERE date<'1960-01-01'
?>
Dupond Grégoire (Grand-
père), date de naissance :
1932-05-17
Dupond Germaine (Grand-
mère), date de naissance :
1939-02-15
Dupond Gérard (Père), date
de naissance : 1959-12-22
8/04/2020 Technologies du Web – ELENA CABRIO
Écrire des données
INSERT : pour rajouter une entrée
UPDATE : modifier des données
UPDATE jeux_video SET prix = 10, nbre_joueurs_max = 32 WHERE ID = 51
DELETE : supprimer des données
DELETE FROM jeux_video WHERE nom='Battlefield 1942'
$sql = "INSERT INTO jeux_video(ID, nom, possesseur, console)
VALUES('', 'Battlefield 1942', 'Patrick', 'PC')”;
// on insère les informations du formulaire dans la table
mysqli_query($sql) or die('Erreur SQL !'.$sql.'<br>'.mysql_error());
8/04/2020 Technologies du Web – ELENA CABRIO
Alimenter une table: an exempleCREATE TABLE infos_tbl (id INT (11) not null AUTO_INCREMENT, nom VARCHAR (35) not null ,
prenom VARCHAR (35) not null , email VARCHAR (70) not null , icq INT (11) null , titre VARCHAR (70)
not null , url VARCHAR (255) not null , PRIMARY KEY (id), INDEX (id), UNIQUE (id))
<html>
<form method="POST" action="add.php">
<center>
<input type="text" name="nom" size="20" value="nom"
maxlength="35">
<input type="text" name="prenom" size="20"
value="prenom" maxlength="35"><br>
<input type="text" name="email" size="20" value="email"
maxlength="70">
<input type="text" name="icq" size="20" value="icq"
maxlength="11"><br>
<input type="text" name="titre" size="20" value="titre du
site" maxlength="70">
<input type="text" name="url" size="20" value="url du
site" maxlength="255"><br>
<input type="submit" value="Envoyer" name="envoyer">
</center>
</form>
</html>8/04/2020 Technologies du Web – ELENA CABRIO
Add.php <?php
// On commence par récupérer les champs
if(isset($_POST['nom'])) $nom=$_POST['nom'];
else $nom="";
if(isset($_POST['prenom'])) $prenom=$_POST['prenom'];
else $prenom="";
if(isset($_POST['email'])) $email=$_POST['email'];
else $email="";
if(isset($_POST['icq'])) $icq=$_POST['icq'];
else $icq="";
if(isset($_POST['titre'])) $titre=$_POST['titre'];
else $titre="";
if(isset($_POST['url'])) $url=$_POST['url'];
else $url="";
// On vérifie si les champs sont vides
if(empty($nom) OR empty($prenom) OR empty($email) OR empty($titre) OR empty($url))
{
echo '<font color="red">Attention, seul le champs <b>ICQ</b> peut rester vide !</font>';
} 8/04/2020 Technologies du Web – ELENA CABRIO
Add.php (cont.)// Aucun champ n'est vide, on peut enregistrer dans la table
else
{
// connexion à la base
$db = mysql_connect('localhost', 'login', 'password') or die('Erreur de connexion '.mysql_error());
// sélection de la base
mysql_select_db('nom_de_la_base',$db) or die('Erreur de selection '.mysql_error());
// on écrit la requête sql
$sql = "INSERT INTO infos_tbl(id, nom, prenom,email, icq, titre,
url) VALUES('','$nom','$prenom','$email','$icq','$titre','$url')";
// on insère les informations du formulaire dans la table
mysql_query($sql) or die('Erreur SQL !'.$sql.'<br>'.mysql_error());
// on affiche le résultat pour le visiteur
echo 'Vos infos on été ajoutées.';
mysql_close(); // on ferme la connexion
}
?>
8/04/2020 Technologies du Web – ELENA CABRIO
References
http://php.net/manual/fr/intro.msql.php
https://openclassrooms.com/courses/concevez-votre-site-web-
avec-php-et-mysql
https://www.w3schools.com/php/php_mysql_intro.asp
http://www.phpdebutant.org/article67.php
8/04/2020 Technologies du Web – ELENA CABRIO
Technologies du WebComment debugger un projet PHP?
Par Elena CABRIO
Basé sur les cours de Jean-Pierre Lozi, Philippe Renevier et Andrea Tettamanzi
8/04/2020 Technologies du Web – ELENA CABRIO
Le débuggage: à quoi ça sert
A la différence de nombreux autres langages, PHP n'est pas
compilé et est donc très avare de messages d'erreurs.
La partie de débuggage est une phase essentielle de la
programmation d'une application, ne serait que pour faire un
rapport de tests : tester chaque fonction afin de voir ce qu'il se
passe dans tous les cas.
Le débuggage est également nécessaire lorsque l'on bloque sur un
truc que l'on ne comprend pas.
8/04/2020 Technologies du Web – ELENA CABRIO
Règles à respecter afin de minimiser le
risque de bug
Aérer le code
<?php
$toto = 3; $titi = 4; $somme = $toto + $titi; echo $somme;
?>
<?php
$toto = 3;
$titi = 4;
$somme = $toto + $titi;
echo $somme;
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Règles à respecter afin de minimiser le risque de
bug (cont.)
Indenter le code, deux possibilités:
<?php
$toto = 2;
if ($toto == 2) {
echo '$toto vaut 2';
}
elseif ($toto == 3) {
echo '$toto vaut 3';
}
else {
echo '$toto n\'est pas
égal à 2 ou 3';
}
?>
<?php
$toto = 2;
if ($toto == 2)
{
echo '$toto vaut 2';
}
elseif ($toto == 3)
{
echo '$toto vaut 3';
}
else
{
echo '$toto n\'est pas
égal à 2 ou 3';
}
?>8/04/2020 Technologies du Web – ELENA CABRIO
Règles à respecter afin de minimiser le
risque de bug (cont.) Commenter le code
<?php
// Ceci est un commentaire sur une seule ligne, style c++/* Ceci est un commentaire sur
plusieurs lignes */
?>
Placez des commentaires sur:
vos fonctions (décrivant les paramètres de la fonction et son rôle)
sur les sections critiques dans votre code (ex. sur une difficulté algorithmique)
dans vos entêtes de classes pour décrire le rôle de votre classe, le genre d'objets qu'elle génère.
Mais attention à ne pas tomber dans l'excès de commentaires…
<?php
// on affiche la somme
echo $somme;
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Quelques petites astuces
Prenez l'habitude (lors de la phase de conception d'un script), d'afficher
le contenu de vos variables
variable de type chaîne de caractères
<?php
$chaine = " test";
echo '.'.$chaine.'.';
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Quelques petites astuces (cont.) variables de type tableau (array)
<?php
$table = array ('a' => 'pomme', 'b' => 'banane', 'c' => array
('x', 'y', 'z'));
print_r ($table);
?>
Array
(
[a] => pomme
[b] => banane
[c] => Array
(
[0] => x
[1] => y
[2] =>
z
)
)
Plus verbal encore que son précédent: la fonction var_dump() donne le type
d'une variable ou des champs d'un tableau etc. ainsi que leur contenu exact et,
pour les chaines, le nombre de caractères.
8/04/2020 Technologies du Web – ELENA CABRIO
Quelques petites astuces (cont.) Cas des conditionnelles
Attention à l'utilisation d'un seul = pour votre test (à la place de ==)
Cas des boucles
si votre boucle ne démarre pas du tout, vérifier la valeur de votre compteur à l'initialisation de la boucle
si votre boucle semble tourner à l'infini, vérifier bien que la valeur pour la sortie de la boucle arrivera à coup sur
Si votre boucle effectue des traitements non voulus sur vos données, prenez l'habitude de placer un echo dans votre boucle afin de voir la valeur de vos variables à chaque passage de boucle
<?php
$toto = 2;
for ($i = 0; $i < 5; $i++) {
$resultat = $toto * $i;
echo 'Passage numéro '.$i.' => multiplication = '.$resultat;
echo '<br />';
}
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Quelques petites astuces (cont.)
Cas des fichiers. Vérifier toujours :
d'une part le chemin pour accéder à votre fichier (chemins relatifs / absolus)
d'autre part le chmod de ce fichier (afin de voir si vous avez les droits pour accéder à ce fichier).
Problèmes avec MySQL
placez vos requêtes SQL dans des variables (par exemple $sql, au lieu de faire directement un mysql_query)
faites un echo de votre $sql, et copier coller votre requête dans votre PHPMyAdmin : si PHPMyAdmin sort bien un résultat, c'est que votre code de récupération est correct.
comptez toujours le nombre de résultat retourné de votre requête SQL à l'aide d'un mysqli_num_rows
mettez un or die muni de la fonction mysqli_error sur vos lancement de requêtes SQL afin de voir (si la requête ne passe pas) ce qui pose problème.
8/04/2020 Technologies du Web – ELENA CABRIO
Afficher les erreurs PHP<?php
// Afficher les erreurs à l'écran
ini_set('display_errors', 1);
// Enregistrer les erreurs dans un fichier de log
ini_set('log_errors', 1);
// Nom du fichier qui enregistre les logs (attention aux droits à l'écriture)
ini_set('error_log', dirname(__file__) . '/log_error_php.txt');
// Afficher les erreurs et les avertissements
error_reporting(e_all);
?>8/04/2020 Technologies du Web – ELENA CABRIO
Configuration pour la gestion d'erreursLe comportement de ces fonctions est affecté par la configuration dans php.ini
display_errors string
détermine si les erreurs doivent être affichées à l'écran ou
int error_reporting ([ int $level ] )
fixe le niveau de rapport d'erreurs PHP
<?php
error_reporting(0); // Désactiver le rapport d'erreurs
error_reporting(E_ERROR | E_WARNING | E_PARSE); // Rapporte les erreurs d'exécution de script
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE); // Rapporter les E_NOTICE peut vousaider à améliorer vos scripts (variables non initialisées, variables mal orthographiées..)
error_reporting(E_ALL ^ E_NOTICE); // Rapporte toutes les erreurs à part les E_NOTICE. C'est la configuration par défaut de php.ini
error_reporting(E_ALL); // Repporte toutes les erreurs PHP (pour PHP 3, utilisez l'entier 63)
ini_set('error_reporting', E_ALL); // Même chose que error_reporting(E_ALL);
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Les messages d'erreurs fréquentsErreur Remède
Parse error: parse error in xxxx.php on line
y
Il s'agit d'une erreur de syntaxe. Vérifiez si:
- vous n'avez pas oublié un ; marquant la
fin d'une instruction
- si il ne manque pas un $ (dollar) devant
le nom d'une variable.
N'hésitez pas à contrôler les lignes
précédentes. L'erreur se trouve souvent
juste au-dessus.
Warning: Unable to create [chemin] No such
file or directory in your script on line
[numero]
Le chemin vers le répertoire censé contenir
le fichier ou bien le chemin du répertoire
dans lequel le fichier doit être crée est
incorrect
Warning: Variable $zzzz is not an array or
string in xxxx.php on line y
Vous tentez de manipuler une valeur
numérique avec une fonction dédiée aux
chaînes ou aux tableaux.
Warning: Cannot add header information
headers already sent in xxxx.php on line y
Vous avez tenté d'effectuer un Header après
que l'entête HTTP ait envoyé au client.
Vérifiez si une sortie (echo, print, message
d'erreur, voir même du code html) ne
s'exécute pas avant votre Header
8/04/2020 Technologies du Web – ELENA CABRIO
Les messages d'erreurs frequents (cont.)Erreur Remède
Fatal error: Maximum execution time
exceeded in xxxx.php on line y
PHP dispose d'un mécanisme permettant de
se prémunir des scripts susceptibles
d'engendrer un temps d'exécution trop
important pouvant saturer un serveur. Par
défaut, ce temps est de 30 secondes.
Fatal Error: Call to undefined function:
xxxx() in yyy.php on line z
La fonction que vous appelez n'existe pas.
Ce peut-être une fonction liée à une
librairie externe. Dans ce cas, un simple
phpinfo() vous renseignera sur les
paramètres de compilation de votre version
de PHP. Peut-être s'agit-il sinon d'une de vos
propres fonctions. Vérifiez alors qu'elle
existe (notamment si votre script y accède
bien si elle se trouve dans un autre fichier).
Et dans tous les cas, contrôlez de plus près
le nom de la fonction appelée (orthographe,
etc.).
Wrong parameter count for %s()
La fonction est appelée avec un nombre
insuffisant de paramètre, ou bien avec trop
de paramètres. Certaines fonctions ont
besoin d'un minimum de paramètres
(array()), et généralement d'un maximum.
8/04/2020 Technologies du Web – ELENA CABRIO
IDE orientés PHP IDE (Integrated Development Environment)
Zend Framework avec NetBeans
8/04/2020 Technologies du Web – ELENA CABRIO
https://noeticforce.com/best-php-ide-for-
programmers-windows-and-mac
Technologies du WebSecurité et PHP (une courte intro)
Par Elena CABRIO
Basé sur les cours de Jean-Pierre Lozi, Philippe Renevier et Andrea Tettamanzi
8/04/2020 Technologies du Web – ELENA CABRIO
Introduction
PHP est un langage puissant et l'interpréteur, qu'il soit inclus dans le serveur
web en tant que module ou bien compilé en version CGI, est capable
d'accéder aux fichiers, d'exécuter des commandes, et d'ouvrir des connexions
réseaux. Toutes ces propriétés rendent fragile la sécurité d'un serveur web.
équilibrer les risques et l'utilisabilité
8/04/2020 Technologies du Web – ELENA CABRIO
Architecture 3-tier ou 3 étages
client serveur
1 2
3
8/04/2020 Technologies du Web – ELENA CABRIO
Architecture 3-tier ou 3 étages
client serveur
1 2
3
8/04/2020 Technologies du Web – ELENA CABRIO
Sécurisation des données
Deux types de flux de données à sécuriser:
Les données entrantes : dans un premier temps, sécurisation des données
qui proviennent de l’utilisateur et donc des formulaires avant de pouvoir les
entrer dans la BDD.
Les données sortantes : puis, sécurisation de l'affichage des données issues
de la BDD.
8/04/2020 Technologies du Web – ELENA CABRIO
Protéction des données entrant dans la BDD
Attaque par injection SQL: le pirate détourne la requête en injectant
du code dans les champs du formulaire
Ex: Détournement de clause WHERE
<?php
$requete = "SELECT * FROM membre
WHERE pseudo = '".$_GET['pseudo']."'
AND password = '".$_GET['password']."' ";
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Protéction des données entrant dans la BDD
Attaque par injection SQL: le pirate détourne la requête en injectant
du code dans les champs du formulaire
Ex: Détournement de clause WHERE
<?php
$requete = "SELECT * FROM membre
WHERE pseudo = '".$_GET['pseudo']."'
AND password = '".$_GET['password']."' ";
?>
8/04/2020 Technologies du Web – ELENA CABRIO
<?php
$_GET['password'] = " ' OR 1 = '1 ";
?>
Protéction des données entrant dans la BDD
Attaque par injection SQL: le pirate détourne la requête en injectant
du code dans les champs du formulaire
Ex: Détournement de clause WHERE
<?php
$requete = "SELECT * FROM membre
WHERE pseudo = '".$_GET['pseudo']."'
AND password = '' OR 1 = '1' ";
?>
8/04/2020 Technologies du Web – ELENA CABRIO
<?php
$_GET['password'] = " ' OR 1 = '1 ";
?>
Protéction des données entrant dans la BDD
Attaque par injection SQL: le pirate détourne la requête en injectant
du code dans les champs du formulaire
Ex: Détournement de la clause DELETE
<?php
$requete = "DELETE FROM membre
WHERE id = '".$_GET['id']."' ";
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Protéction des données entrant dans la BDD
Attaque par injection SQL: le pirate détourne la requête en injectant
du code dans les champs du formulaire
Ex: Détournement de la clause DELETE
<?php
$requete = "DELETE FROM membre
WHERE id = '".$_GET['id']."' ";
?>
8/04/2020 Technologies du Web – ELENA CABRIO
<?php
$_GET['id'] = "1 ' OR id > '0 ";
?>
Protéction des données entrant dans la BDD
Attaque par injection SQL: le pirate détourne la requête en injectant
du code dans les champs du formulaire
Ex: Détournement de la clause DELETE
<?php
$requete = "DELETE FROM membre
WHERE id = '1' OR id > '0' ";
?>
8/04/2020 Technologies du Web – ELENA CABRIO
<?php
$_GET['id'] = "1 ' OR id > '0 ";
?>
Les magic quotes : la fausse bonne idée...
Il faut protéger les données issues du formulaire avant de les entrer dans la requête
Echapper les valeurs pour les rendre inertes et sans danger
Directive PHP: magic_quotes, qui propose de échapper systématiquement les caractères suivant :
les guillemets simples ' ;
les guillemets doubles " ;
les slashes / ;
les caractères NULL.
en ajoutant des antislashes dans les chaînes qui transitent vers le script PHP (= fonction addslashes()).
<?php
$requete = "DELETE FROM membre
WHERE id = '".$_GET['id']."' ";
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Les magic quotes : la fausse bonne idée...
Il faut protéger les données issues du formulaire avant de les entrer dans la requête
Echapper les valeurs pour les rendre inertes et sans danger
Directive PHP: magic_quotes, qui propose de échapper systématiquement les caractères suivant :
les guillemets simples ' ;
les guillemets doubles " ;
les slashes / ;
les caractères NULL.
en ajoutant des antislashes dans les chaînes qui transitent vers le script PHP (= fonction addslashes()).
<?php
$requete = "DELETE FROM membre
WHERE id = '".$_GET['id']."' ";
?>
8/04/2020 Technologies du Web – ELENA CABRIO
<?php
$requete = "SELECT pseudo FROM membre
WHERE id = '\"1\"mettez l'injection que vous voulez ici\"' ";
?>
Fonction mysqli_real_escape_string() Echappe les caractères suivants:
les guillemets simples ' ;
les guillemets doubles " :
les slashes / ;
les caractères NULL ;
les caractères suivants : , , \x00 et \x1a.
utiliser cette fonction pour sécuriser les chaînes transmises aux requêtes (il faut aussi que vos données soient placées dans des guillemets)
<?php
$pseudo = mysqli_real_escape_string($_POST['pseudo']);
$requete = "SELECT * FROM membre WHERE pseudo =
'$pseudo' ";
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Injection HTML - Cross-Site Scripting (XSS)
Si les données ne sont pas protégés à l'affichage, les pirates peuvent entrer des balises
nocives et notamment du JavaScript
<html>
<head>
<title>Injection HTML</title>
</head>
<body>
<?php echo "Salut, tu t'appelles ".$_GET['pseudo']; ?>
</body>
</html>
8/04/2020 Technologies du Web – ELENA CABRIO
Injection HTML - Cross-Site Scripting (XSS)
Si les données ne sont pas protégés à l'affichage, les pirates peuvent entrer des balises
nocives et notamment du JavaScript
<html>
<head>
<title>Injection HTML</title>
</head>
<body>
<?php echo "Salut, tu t'appelles ".$_GET['pseudo']; ?>
</body>
</html>
8/04/2020 Technologies du Web – ELENA CABRIO
http://monsiteweb.com/index.php?pseudo=%3Ci%3zozor%3C%2Fi%3E
Injection HTML - Cross-Site Scripting (XSS)
Si les données ne sont pas protégés à l'affichage, les pirates peuvent entrer des balises
nocives et notamment du JavaScript
<html>
<head>
<title>Injection HTML</title>
</head>
<body>
<?php echo "Salut, tu t'appelles ".$_GET['pseudo']; ?>
</body>
</html>
8/04/2020 Technologies du Web – ELENA CABRIO
http://monsiteweb.com/index.php?pseudo=<i>zozor</i>
Function htmlentities()
Rend toutes les balise XHTML inopérantes
<html>
<head>
<title>Injection HTML</title>
</head>
<body>
<?php echo "Salut, tu t'appelles htmlentities($_GET['pseudo']);?>
</body>
</html>
http://monsiteweb.com/index.php?pseudo=<i>zozor</i><script
src="http://sitepirate.com/injection.js" >
8/04/2020 Technologies du Web – ELENA CABRIO
Injection HTML - Cross-Site Scripting (XSS)
Si les données ne sont pas protégés à l'affichage, les pirates peuvent entrer des
balises nocives et notamment du JavaScript
<html>
<head>
<title>Injection HTML</title>
</head>
<body>
<?php echo "Salut, tu t'appelles ".$_GET['pseudo']; ?>
</body>
</html> http://monsiteweb.com/index.php?pseudo=<i>zozor</i><script
src="http://sitepirate.com/injection.js" >
<body>
<i>zozor</i><script src="injection.js"
>
</body>
8/04/2020 Technologies du Web – ELENA CABRIO
Fonction htmlspecialchars()
version moins complète de htmlentities()
remplace les caractères suivants par leur entité HTML :
Les délimiteurs de balise < et > ;
Les guillemets simples ' ;
Les guillemets doubles " ;
Le "et commercial" &.
mieux utiliser htmlentities() si vous n'êtes pas certain de maîtriser vos
charsets
8/04/2020 Technologies du Web – ELENA CABRIO
Les listes : contrôle des données
Une liste blanche correspond à l'ensemble des données que l'internaute a le droit de
rentrer
Exemple: Pays d’origine
<?php
$liste_pays = array(
'Belgique',
'Canada',
'France',
'Hongrie',
'Slovénie'
);
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Les listes : contrôle des données
Une liste blanche correspond à l'ensemble des données que l'internaute a le droit de
rentrer
Exemple: Pays d’origine
<?php
$liste_pays = array(
'Belgique',
'Canada',
'France',
'Hongrie',
'Slovénie'
);
?>
8/04/2020 Technologies du Web – ELENA CABRIO
<?php
$pays_transmis = $_POST['pays'];
// Vérification de la présence du pays dans la liste
if(in_array($pays_transmis, $liste_pays))
{
echo 'pays valide.';
}
else
{
echo 'pays invalide, veuillez ressaisir votre
pays. ';
}
?>
Les listes : contrôle des données
La liste noire filtre les données interdites
<?php
$liste_insulte = array(
'crapule',
'chenapan',
'goujat',
'manant'
);
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Les listes : contrôle des données
La liste noire filtre les données interdites
<?php
$liste_insulte = array(
'crapule',
'chenapan',
'goujat',
'manant'
);
?>
<?php
// Récupération depuis une BDD
$message = $resultat['message'];
// Le message est considéré comme valide
$autorisation = true;
// On parcourt toutes les insultes de la liste noire
foreach($liste_insulte as $insulte)
{
// Si une insulte est comprise dans le message
if(stripos($message, $insulte) !== false)
{
$autorisation = false;
break;
}
}
?>
8/04/2020 Technologies du Web – ELENA CABRIO
Les listes : contrôle des données
Liste grise: utilisation en complément la liste blanche et la liste
noire:
une liste blanche qui autorise seulement des valeurs données ;
une liste noire qui filtre les données incorrectes.
Le filtrage des données est considérablement
augmenté !
8/04/2020 Technologies du Web – ELENA CABRIO
Petite synthèse :
Protéger les chaînes de caractères dans les requêtes, la
meilleure solution à ce jour étant la préparation des
requêtes ;
Protéger les données affichées par le navigateur avec
htmlentities() ;
Mettre en place un filtre systématique par liste grise.
8/04/2020 Technologies du Web – ELENA CABRIO
References
http://www.lephpfacile.com/cours/20-le-debuggage
http://php.net/manual/fr/security.intro.php
8/04/2020 Technologies du Web – ELENA CABRIO