PHP
Langages web L2
Olivier Mallet
Université de Rouen
1 Introduction
2 Notions fondamentales
3 Transmettre des données de page en page
4 Programmation objet et applications
5 Aspects avancés
6 Quelques remarques sur la sécurité
Introduction
Généralités sur PHP
Langage exécuté côté serveur
Code PHP inséré dans une page HTML s’il doit produire une sortie
HTML
Toujours dans un bloc <?php ... ?>
Manuel en français : [Link]
Olivier Mallet (Université de Rouen) PHP 3 / 106
Notions fondamentales Chaînes de caractères
Rappels sur les chaînes de caractères
Encadrées par ’’ (contenu non interprété) ou "" (contenu interprété)
Attention à l’échappement des guillemets
Concaténation avec .
Accès à un caractère avec la notation $ch[$i]
Principales fonctions :
strlen($ch) longueur de la chaîne $ch
substr($ch, $debut, $longueur) sous-chaîne de $ch commençant au
caractère d’indice $debut et de longueur $longueur
explode($sep, $ch) découpe la chaîne $ch selon le séparateur $sep et
stocke les éléments dans un tableau
ltrim($ch) / rtrim($ch) / trim($ch) supprime les caractères blancs
(espaces, tabulations, sauts de ligne) de $ch à gauche /
à droite / des deux côtés
Olivier Mallet (Université de Rouen) PHP 4 / 106
Notions fondamentales Chaînes de caractères
Fonctions sur les chaînes de caractères
strstr($ch, $motif) / stristr($ch, $motif) renvoie la partie de la chaîne
commençant à la 1re occurrence du motif (recherche sensible
/ insensible à la casse)
Exemple
echo strstr("Dodo l’enfant do", "do"); // affiche : do l’enfant do
echo stristr("Dodo l’enfant do", "do"); // affiche : Dodo l’enfant do
strpos($ch, $motif) / stripos($ch, $motif) position de la 1re occurrence
du motif (recherche sensible / insensible à la casse)
Exemple
echo strpos("Dodo l’enfant do", "do"); // affiche : 2
echo stripos("Dodo l’enfant do", "do"); // affiche : 0
Les fonctions de recherche renvoient false si le motif n’est pas trouvé.
Olivier Mallet (Université de Rouen) PHP 5 / 106
Notions fondamentales Chaînes de caractères
Fonctions sur les chaînes de caractères (2)
str_replace($motif, $motif2, $ch) / str_ireplace($motif, $motif2, $ch)
remplacement de motifs sensible / insensible à la casse
Exemple
echo str_replace("do", "mi", "Dodo l’enfant do"); // affihe : Domi l’enfant mi
echo str_ireplace("do", "mi", "Dodo l’enfant do"); // affiche : mimi l’enfant mi
strtr($ch, $a_remplacer, $remplacement) remplacement de caractères
(octet par octet ⇒ pas pour un encodage UTF-8 !)
Exemple
$ch = "leetspeak";
$ch2 = strtr($ch, "aeklpst", "@3X1957");
echo $ch2; // affiche : 1337593@X
Olivier Mallet (Université de Rouen) PHP 6 / 106
Notions fondamentales Chaînes de caractères
Fonctions sur les chaînes de caractères (3)
Autre syntaxe pour la dernière fonction : strtr($ch, $remplacements) où
$remplacements est un tableau associatif dont les valeurs sont des chaînes
Chaque occurrence d’une clé de ce tableau dans la chaîne sera remplacée
par la valeur associée
Exemple
$ch = "Bonjour les amis";
$remp = ["jour" => "soir", "les" => "mes chers"];
echo strtr($ch, $remp); // affiche : Bonsoir mes chers amis
Cette syntaxe permet de remplacer les lettres accentuées en UTF-8 :
Exemple
$ch = "J’élève des chèvres à la campagne";
$remp = ["à" => "a", "é" => "e", "è" => "e"];
echo strtr($ch, $remp); // affiche : J’eleve des chevres a la campagne
Olivier Mallet (Université de Rouen) PHP 7 / 106
Notions fondamentales Chaînes de caractères
Expressions régulières en PHP
ER de la forme "/motif/" ou "/motif/options" (on peut utiliser à la
place du / tout caractère alphanumérique autre qu’un \ ou un espace)
À part ça, même syntaxe qu’en JavaScript
preg_match($expreg, $chaine [,$res]) teste si la chaîne contient un motif
correspondant à $expreg et le place dans $res[0] si $res est fourni
Les autres cases de $res reçoivent les motifs correspondant aux
parenthèses capturantes
preg_replace($motif1, $motif2, $chaine) remplace $motif1 par $motif2
dans $chaine
On peut utiliser les parenthèses capturantes (les motifs sont stockés
dans les variables $1, $2,. . ., $99 ; $0 contient toute la regexp)
Rajouter ?: après le ( pour avoir une parenthèse non capturante
Olivier Mallet (Université de Rouen) PHP 8 / 106
Notions fondamentales Chaînes de caractères
Expressions régulières : exemples
Exemple (Vérification d’une adresse électronique)
$er = "/^[a-z0-9._-]+@[a-z0-9._-]+\.[a-z]{2,4}$/i";
if (preg_match($er, $_POST[’email’]))
echo "Cette adresse email est valide";
else
echo "Cette adresse email n’est pas valide";
Exemple (Recherche de motifs)
$er = "/^([a-z0-9._-]+)@([a-z0-9._-]+)\.([a-z]{2,4})$/i";
if (preg_match($er, "[Link]@[Link]", $res))
echo implode(", ",$res);
// affiche : [Link]@[Link], [Link], univ-rouen, fr
Olivier Mallet (Université de Rouen) PHP 9 / 106
Notions fondamentales Chaînes de caractères
Expressions régulières : exemples (2)
Exemple (Suppression des espaces superflus)
$ch = ’Un texte avec des espaces en trop’;
$ch = preg_replace(’/\s\s+/’, ’ ’, $ch);
echo $ch; // affiche : Un texte avec des espaces en trop
Exemple (Transformation d’une adresse électronique)
$email = "Contact : toto@[Link]";
$email = preg_replace("/([a-z0-9._-]+)@([a-z0-9._-]+)\.([a-z]{2,6})/", "$1
{à} $2 {point} $3", $email);
echo $email; // affiche : Contact : toto {à} exemple {point} com
Olivier Mallet (Université de Rouen) PHP 10 / 106
Notions fondamentales Chaînes de caractères
Fonctions en rapport avec la date et l’heure
mktime($h, $m, $s, $mo, $j, $a) renvoie le nombre de secondes entre le
1/1/1970 à minuit et l’instant indiqué (timestamp Unix)
Exemple
$instant = mktime(1, 2, 3, 4, 5, 2020);
echo $instant; // affiche : 1586041323
date($format [, $timestamp]) renvoie une chaîne de caractères
représentant la date du timestamp au format spécifié (ou la
date actuelle si pas de timestamp)
Exemple
echo date("d/m/Y, H:i:s", $instant); // affiche : 05/04/2020, 01:02:03
Olivier Mallet (Université de Rouen) PHP 11 / 106
Notions fondamentales Chaînes de caractères
Encodage et décodage JSON
json_encode($expr) renvoie la représentation JSON de $expr sous
forme de chaîne de caractères
Exemple
$personne = ["prenom"=>"Jean","nom"=>"Dupont","age"=>42];
echo json_encode($personne);
// affiche : {"prenom":"Jean","nom":"Dupont","age":42}
json_decode ($ch [, $tableau]) décode la chaîne JSON $ch ; les objets
JSON sont décodés sous forme d’objets (ou de tableau associatif si
$tableau est fourni et vaut true )
Exemple
$json = ’{"prenom":"Jean","nom":"Dupont","age":42}’;
$obj = json_decode($json); // $obj contient un objet (voir plus loin)
$tab = json_decode($json, true); // tab est un tableau associatif
Olivier Mallet (Université de Rouen) PHP 12 / 106
Notions fondamentales Tableaux
Fonctions de tri
Tri simple :
sort($tab) trie dans l’ordre des valeurs
rsort($tab) trie dans l’ordre inverse des valeurs
usort($tab, $fonc) trie dans l’ordre des valeurs, donné par une
fonction
Tri associatif (conserve l’association clé - valeur) :
asort($tab) trie dans l’ordre des valeurs
arsort($tab) trie dans l’ordre inverse des valeurs
ksort($tab) trie dans l’ordre des clés
krsort($tab) trie dans l’ordre inverse des clés
uasort($tab, $fonc) trie dans l’ordre des valeurs, donné par une
fonction
uksort($tab, $fonc) trie dans l’ordre des clés, donné par une fonction
Ces fonctions ne renvoient rien ; elles modifient le tableau $tab
Olivier Mallet (Université de Rouen) PHP 13 / 106
Notions fondamentales Tableaux
Trier selon un ordre donné par une fonction
Exemple (On trie pour avoir les nombres pairs dans l’ordre croissant
puis les impairs dans l’ordre croissant)
function triPairImpair($a, $b) {
if ($a == $b)
return 0; // on renvoie 0 si $a==$b
if (($a % 2 == 0) and ($b % 2 != 0))
return -1; // on renvoie une valeur < 0 si $a < $b
if (($a % 2 != 0) and ($b % 2 == 0))
return 1; // on renvoie une valeur > 0 si $a > $b
return ($a > $b) ? 1 : -1;
}
$tab = [4, 3, 6, 8, 2, 5, 1];
usort($tab, "triPairImpair");
echo implode(",", $tab); // affiche : 2,4,6,8,1,3,5
Olivier Mallet (Université de Rouen) PHP 14 / 106
Notions fondamentales Opérateurs
Opérateurs bit à bit
& et
| ou
ˆ ou exclusif
˜ négation
<< décalage à gauche
>> décalage à droite
Olivier Mallet (Université de Rouen) PHP 15 / 106
Notions fondamentales Structures de contrôle
Boucles : do... while
do {
...
}
while (condition); // condition testée après chaque étape
Exemple (Ce code affiche 0 puis sort de la boucle)
$i = 0;
do {
echo $i;
} while ($i > 0);
Olivier Mallet (Université de Rouen) PHP 16 / 106
Notions fondamentales Fonctions
Fonctions
function ma_fonction($arg1, $arg2, ...) {
instructions;
return ...; // si la fonction renvoie une valeur
}
Passage des paramètres par valeur
Pour passer un paramètre par référence, rajouter & devant son nom
dans l’en-tête de la fonction
Exemple
function f($x, &$y) {$x++; $y++; echo "x = $x, y = $y";}
$a = 0; $b = 5;
f($a, $b); // affiche : x = 1, y = 6
echo "a = $a, b = $b"; // affiche : a = 0, b = 6
Olivier Mallet (Université de Rouen) PHP 17 / 106
Notions fondamentales Fonctions
Fonction avec un nombre variable d’arguments
func_num_args() : renvoie le nombre d’arguments de la fonction
func_get_args() : renvoie les arguments de la fonction sous forme de
tableau
func_get_arg($i) : renvoie le (i + 1)e argument de la fonction (i ≥ 0)
Exemple (Fonction acceptant un nombre variable d’arguments)
function somme() {
$s = 0;
$tab = func_get_args();
for($i = 0; $i < count($tab); $i++)
$s += $tab[$i];
return $s;
}
echo somme(1, 3); // affiche : 4
echo somme(1, 5, -2, 8); // affiche : 12
Olivier Mallet (Université de Rouen) PHP 18 / 106
Notions fondamentales Inclusion de fichiers
Inclusion de fichiers
include : inclut un fichier ou provoque un avertissement s’il n’est pas
trouvé
require : idem mais erreur si fichier non trouvé
include_once , require_once : le fichier n’est inclus que s’il n’a pas
déjà été inclus
Exemple
Si le fichier [Link] contient <?php echo "OK"; ?> , le code
echo "Inclusion 1 : ";
include "[Link]";
echo ", inclusion 2 : ";
include_once "[Link]";
affiche « Inclusion 1 : OK, inclusion 2 : ».
Olivier Mallet (Université de Rouen) PHP 19 / 106
Transmettre des données de page en page Traitement de formulaires
Formulaires
Champ de formulaire HTML avec name="mon_nom" −→ variable PHP
définie dans la page de traitement :
Nom :
$_GET[’mon_nom’] si données envoyées par GET
$_POST[’mon_nom’] si données envoyées par POST
Valeur : texte entré ou valeur de l’attribut value du champ
Type :
chaîne de caractères (cas général)
tableau (pour un groupe de cases à cocher ou une liste de sélection à
choix multiple)
Olivier Mallet (Université de Rouen) PHP 20 / 106
Transmettre des données de page en page Traitement de formulaires
Cas où on transmet un tableau
Exemple
Formulaire HTML :
<form action="[Link]" method="post">
<p>Choix 1<input type="checkbox" name="var[]" value="1" /></p>
<p>Choix 2<input type="checkbox" name="var[]" value="2" /></p>
<p>Choix 3<input type="checkbox" name="var[]" value="3" /></p>
<p><input type="submit" value="Envoyer !" /></p>
</form>
Traitement PHP :
echo implode(", ", $_POST[’var’]);
// affiche : 1, 3 si on a choisi 1 et 3
Olivier Mallet (Université de Rouen) PHP 21 / 106
Transmettre des données de page en page Traitement de formulaires
Récupération d’un fichier envoyé par l’utilisateur
HTML : champ <input type="file" name="mon_fichier" />
PHP : variable $_FILES[’mon_fichier’] = tableau associatif
$_FILES[’mon_fichier’][’name’] : chemin d’accès original du fichier
$_FILES[’mon_fichier’][’type’] : type du fichier (déterminé à partir de
l’extension)
$_FILES[’mon_fichier’][’size’] : taille du fichier (en octets)
$_FILES[’mon_fichier’][’tmp_name’] : chemin d’accès au fichier sur le
serveur (répertoire temporaire)
$_FILES[’mon_fichier’][’error’] : code indiquant si le fichier a bien été
reçu par le serveur (UPLOAD_ERR_OK si c’est le cas)
On peut ainsi faire des vérifications avant d’accepter le fichier
Déplacer le fichier dans son répertoire de stockage définitif :
move_uploaded_file($chemin_origine, $chemin_destination) (renvoie true
si le fichier a bien été déplacé, false sinon)
Olivier Mallet (Université de Rouen) PHP 22 / 106
Transmettre des données de page en page Traitement de formulaires
Récupération d’un fichier envoyé par l’utilisateur : exemple
Exemple
if (isset($_FILES[’image’]) and
$_FILES[’image’][’error’] == UPLOAD_ERR_OK) {
if ($_FILES[’image’][’type’] == "image/png" and
$_FILES[’image’][’size’] <= 1000000) {
$resultat = move_uploaded_file($_FILES[’image’][’tmp_name’],
"images/".basename($_FILES[’image’][’name’]));
// basename permet de récupérer le nom sans le chemin d’accès
if ($resultat)
echo "C’est bon !";
}
Attention !
Il faut avoir les droits d’écriture sur le répertoire de destination (à
changer si besoin est avec chmod)
Olivier Mallet (Université de Rouen) PHP 23 / 106
Transmettre des données de page en page Manipulation de fichiers
Modes d’ouverture d’un fichier
Rappel : on ouvre un fichier avec fopen($chemin, $mode)
r lecture seule, pointeur au début du fichier
w écriture seule, pointeur au début du fichier
le fichier est vidé s’il existe, créé s’il n’existe pas
a écriture seule, pointeur à la fin du fichier
le fichier est créé s’il n’existe pas
x écriture seule, pointeur au début du fichier
le fichier est créé (s’il existe, fopen échoue et renvoie false )
c écriture seule, pointeur au début du fichier
le fichier est créé s’il n’existe pas
r+ lecture et écriture ; à part ça, identique à r
w+, a+. . . même principe
Olivier Mallet (Université de Rouen) PHP 24 / 106
Transmettre des données de page en page Gestion de sessions
Sessions
Une variable PHP n’existe que pendant l’exécution du script où elle
est définie
Comment conserver des informations sur un utilisateur d’une page à
l’autre ?
Identité d’un utilisateur authentifié
Panier d’achat
Solutions : cookies ou sessions PHP
Olivier Mallet (Université de Rouen) PHP 25 / 106
Transmettre des données de page en page Gestion de sessions
Cookies
Cookie : couple nom - valeur déposé par un site web sur l’ordinateur
d’un utilisateur
Les cookies d’un site sont renvoyés au serveur par le navigateur quand
on navigue sur les pages de ce site
Permettent de garder des informations d’une session à l’autre (en
donnant une date d’expiration)
Un utilisateur peut refuser les cookies
Il peut aussi les modifier car ils sont sur son ordinateur
Olivier Mallet (Université de Rouen) PHP 26 / 106
Transmettre des données de page en page Gestion de sessions
Les cookies en PHP
Déposer un cookie chez l’utilisateur : setcookie($nom, $valeur)
Déposer un cookie avec une date d’expiration (timestamp Unix) :
setcookie($nom, $valeur, $date_expi)
Exemple (Cookie expirant le 1er juillet 2010 à 12h)
setcookie("prenom", "Jean", mktime(12, 0, 0, 7, 1, 2010));
Modifier la valeur d’un cookie : setcookie($nom, $nouvelle_valeur)
Supprimer un cookie : setcookie($nom)
Les cookies sont envoyés dans l’en-tête de la réponse HTTP ⇒ il faut
appeler setcookie avant de commencer à construire la page HTML
Les valeurs des cookies envoyés par le navigateur sont stockées dans
le tableau associatif $_COOKIE
Exemple
echo $_COOKIE[’prenom’]; // affiche : Jean
Olivier Mallet (Université de Rouen) PHP 27 / 106
Transmettre des données de page en page Gestion de sessions
Sessions PHP
Une session est repérée par un identifiant unique
Cet identifiant est transmis d’une page à l’autre dans un cookie ou
dans l’URL
Les données à conserver au cours de la session sont stockées dans le
tableau $_SESSION
Pour créer une session (ou poursuivre la session en cours) :
session_start()
Indispensable pour pouvoir utiliser les variables de session
À placer au tout début de la page (comme setcookie)
Pour détruire une session : session_destroy()
Ne supprime ni les variables de session (pour ça, faire
$_SESSION = []; ) ni le cookie (utiliser setcookie)
PHP supprime tout seul les sessions au bout d’un certain temps
Olivier Mallet (Université de Rouen) PHP 28 / 106
Programmation objet et applications Les objets en PHP
Introduction
Le mécanisme objet de PHP utilise des classes (« moules à objets »)
Une classe regroupe des attributs, un constructeur et des méthodes
Tout objet créé à l’aide du constructeur d’une classe disposera des
attributs et des méthodes définis par cette classe
Visibilité des attributs et des méthodes :
Publics : accessibles de n’importe où
Privés : accessibles uniquement depuis l’intérieur de la classe
Olivier Mallet (Université de Rouen) PHP 29 / 106
Programmation objet et applications Les objets en PHP
Création d’une classe
Exemple
class Voiture {
// attributs
private $marque;
private $kilometrage;
public $couleur;
// constructeur
function __construct($marque, $couleur) {
$this->marque = $marque;
$this->kilometrage = 0;
$this->couleur = $couleur;
}
Visibilité : public (par défaut), protected (voir plus loin) ou private
Olivier Mallet (Université de Rouen) PHP 30 / 106
Programmation objet et applications Les objets en PHP
Création d’une classe (suite)
Exemple
// méthodes
function getMarque() {
return $this->marque;
}
function getKilometrage() {
return $this->kilometrage;
}
function avancer($distance) {
$this->kilometrage += $distance;
}
}
Olivier Mallet (Université de Rouen) PHP 31 / 106
Programmation objet et applications Les objets en PHP
Création et utilisation d’un objet
Exemple
$maVoiture = new Voiture("Lada", "rouge");
echo "J’ai une voiture de marque ".$maVoiture->getMarque();
echo " et de couleur ".$maVoiture->couleur.". ";
echo "Elle a ".$maVoiture->getKilometrage()." km.<br />";
$maVoiture->avancer(10);
echo "Maintenant, elle a ".$maVoiture->getKilometrage()." km.";
affiche :
J’ai une voiture de marque Lada et de couleur rouge. Elle a 0 km.
Maintenant, elle a 10 km.
Remarque
L’objet $maVoiture a été créé à l’aide du constructeur de la classe Voiture.
On dit que c’est une instance de cette classe.
Olivier Mallet (Université de Rouen) PHP 32 / 106
Programmation objet et applications Les objets en PHP
Attributs et méthodes statiques
S’appliquent à une classe et non à un objet
Attributs et méthodes statiques : précédés du mot-clé static
Constantes statiques : const MA_CONSTANTE = 0;
Accès à un attribut, une constante ou une méthode statique :
Depuis la même classe : self::$monAttribut , self::maMethode ,
self::MA_CONSTANTE
Depuis une autre classe : MaClasse::$monAttribut ,
MaClasse::maMethode , MaClasse::MA_CONSTANTE
Olivier Mallet (Université de Rouen) PHP 33 / 106
Programmation objet et applications Les objets en PHP
Attributs et méthodes statiques : exemple
class Personnage {
public const NIVEAU_MAX = 10;
public static $nbPersonnages = 0;
private $niveau;
function __construct() {
$this->niveau = 1;
self::$nbPersonnages += 1;
}
function getNiveau() {return $this->niveau;}
}
$p = new Personnage();
if($p->getNiveau() > Personnage::NIVEAU_MAX)
echo "Erreur, ce personnage est un mutant !";
Olivier Mallet (Université de Rouen) PHP 34 / 106
Programmation objet et applications Les objets en PHP
Héritage
Exemple
class Personnage {
public function combattre($ennemi) {
// ...
}
}
class Sorcier extends Personnage {
public function combattre($ennemi) {
// on peut redéfinir la méthode
}
public function soigner($compagnon) {
// méthode spécifique à cette classe
}
}
Olivier Mallet (Université de Rouen) PHP 35 / 106
Programmation objet et applications Les objets en PHP
Héritage (2)
Toute instance de Sorcier dispose des propriétés publiques ou
protégées définies dans Personnage (la classe Sorcier peut les
redéfinir et en ajouter d’autres)
Une classe ne peut hériter que d’une seule autre classe
Olivier Mallet (Université de Rouen) PHP 36 / 106
Programmation objet et applications Les objets en PHP
Classes abstraites
Méthode abstraite : déclaration de méthode non implémentée
(précédée du mot-clé abstract )
Une classe contenant des méthodes abstraites doit être déclarée
abstraite
Une classe qui hérite d’une classe abstraite et n’implémente pas
toutes ses méthodes doit aussi être déclarée abstraite
Exemple
abstract class Personne {
private $nom;
public function getNom() {
return $this->nom;
}
abstract public function enregistrer();
}
Olivier Mallet (Université de Rouen) PHP 37 / 106
Programmation objet et applications Les objets en PHP
Classes abstraites : suite de l’exemple
Exemple
class Etudiant extends Personne() {
private $filiere;
public function enregistrer() {
// écrire le nom dans la table Etudiants
}
}
class Employe extends Personne() {
private $numeroEmploye;
public function enregistrer() {
// écrire le nom dans la table Employes
}
}
Olivier Mallet (Université de Rouen) PHP 38 / 106
Programmation objet et applications Les objets en PHP
Interfaces
Contiennent des constantes et des déclarations de méthodes
(publiques)
Une classe qui implémente une interface dispose des constantes de
celle-ci et doit définir toutes les méthodes qu’elle déclare
Une classe peut implémenter plusieurs interfaces
Les interfaces s’étendent comme les classes avec extends
Olivier Mallet (Université de Rouen) PHP 39 / 106
Programmation objet et applications Les objets en PHP
Interfaces : exemple
Exemple
interface Radio {
const maxFreq=108;
public function retransmettre($freq);
}
interface Reveil {
public function sonner($h, $m);
}
class RadioReveil implements Radio, Reveil {
public function retransmettre($freq) {echo "Vous ecoutez $freq";}
public function sonner ($h, $m) {
echo "Il est $h:$m, il faut se lever !";
}
}
Olivier Mallet (Université de Rouen) PHP 40 / 106
Programmation objet et applications Exceptions
Exceptions
Lancer une exception : throw new Exception($message);
L’objet lancé doit être une instance de la classe Exception ou d’une
sous-classe
Bloc try : code susceptible de déclencher une exception
Bloc catch : code exécuté si une exception est lancée
On peut ajouter un bloc finally après le(s) catch : code exécuté dans
tous les cas (que l’exception soit lancée ou non)
Remarque
Les fonctions prédéfinies de PHP déclenchent en général des erreurs et non
des exceptions, sauf pour les extensions orientées objet comme PDO (voir
la section suivante).
Olivier Mallet (Université de Rouen) PHP 41 / 106
Programmation objet et applications Exceptions
Exceptions : exemple
function inverse($x) {
if ($x == 0) {
throw new Exception("Division par 0");
}
return 1/$x;
}
try {
echo inverse(5) . " ";
echo inverse(0);
}
catch (Exception $e) {
echo "Exception : ".$e->getMessage();
}
// affiche : 0.2 Exception : Division par 0
Olivier Mallet (Université de Rouen) PHP 42 / 106
Programmation objet et applications Accès aux bases de données
L’interface PDO (PHP Data Objects)
Interface unifiée pour l’accès aux bases de données en PHP
Fait intervenir 3 classes :
PDO (connexion à la base de données)
PDOStatement (requêtes et résultats)
PDOException (traitement des erreurs)
Olivier Mallet (Université de Rouen) PHP 43 / 106
Programmation objet et applications Accès aux bases de données
Connexion à la base de données
On appelle le constructeur de PDO avec 3 paramètres :
DSN (Data Source Name) : chaîne qui contient le nom du serveur et
celui de la base (la syntaxe dépend du SGBD)
nom d’utilisateur (facultatif pour certains SGBD)
mot de passe (facultatif pour certains SGBD)
Il est conseillé de mettre l’appel dans un bloc try - catch
Exemple (Connexion à une base de données MySQL)
try {
$dsn = "mysql:host=[Link];dbname=mabase";
$connexion = new PDO($dsn, "duponjea", "123456");
}
catch(PDOException $e) {
exit(’Erreur : ’.$e->getMessage());
}
Pour fermer la connexion : unset($connexion); ou $connexion = null;
Olivier Mallet (Université de Rouen) PHP 44 / 106
Programmation objet et applications Accès aux bases de données
Requête SELECT
Appel de la forme $connexion->query($requete) qui renvoie une
instance de PDOStatement (ou false en cas d’erreur)
Pour récupérer une ligne du résultat (sous forme de tableau), on
appelle la méthode fetch() sur cet objet
Il existe aussi une méthode fetchAll() qui renvoie un tableau
contenant toutes les lignes du résultat
Exemple
$requete = "SELECT * FROM Etudiants WHERE moyenne >= 10";
$res = $connexion->query($requete);
while ($etu = $res->fetch()) {
echo "<tr><td>".$etu[’nom’]."</td><td>".$etu[’prenom’]."</td>";
echo "<td>".$etu[’moyenne’]."</td></tr>";
}
Olivier Mallet (Université de Rouen) PHP 45 / 106
Programmation objet et applications Accès aux bases de données
Le même exemple avec fetchAll
Exemple
$requete = "SELECT * FROM Etudiants WHERE moyenne >= 10";
$res = $connexion->query($requete);
$lignes = $res->fetchAll();
foreach($lignes as $etu) {
echo "<tr><td>".$etu[’nom’]."</td><td>".$etu[’prenom’]."</td>";
echo "<td>".$etu[’moyenne’]."</td></tr>";
}
Olivier Mallet (Université de Rouen) PHP 46 / 106
Programmation objet et applications Accès aux bases de données
Requête INSERT, UPDATE ou DELETE
Appel de la forme $connexion->exec($requete) qui renvoie le nombre de
lignes modifiées ou effacées (ou false en cas d’erreur)
Exemple (On remonte les notes des étudiants qui ont entre 9,5 et 10)
$requete = "UPDATE Etudiants SET moyenne = 10 WHERE moyenne >= 9.5
AND moyenne < 10";
$retour = $connexion->exec($requete);
if($retour === false) // === permet de distinguer false et 0
echo "Erreur";
else
echo "$retour moyennes ont ete changees";
Olivier Mallet (Université de Rouen) PHP 47 / 106
Programmation objet et applications Accès aux bases de données
Requêtes préparées
Principe : on crée un modèle de requête qu’on enregistre dans le
SGBD pendant la durée d’exécution du script
On fait ensuite appel à ce modèle pour exécuter concrètement des
requêtes
PDO émule les requêtes préparées si le SGBD ne les prend pas en
charge
Olivier Mallet (Université de Rouen) PHP 48 / 106
Programmation objet et applications Accès aux bases de données
Intérêts des requêtes préparées
La requête n’est interprétée qu’une fois mais peut être exécutée
plusieurs fois (avec des paramètres éventuellement différents) ⇒ gain
de temps (on ne répète pas tout le cycle d’exécution)
Les paramètres des requêtes préparées sont protégés contre les
attaques par injection SQL
source : [Link]
Olivier Mallet (Université de Rouen) PHP 49 / 106
Programmation objet et applications Accès aux bases de données
Construction d’une requête préparée
Écrire la requête :
Requête avec des points d’interrogation
Exemple
$sql = "INSERT INTO Etudiants(nom, prenom, moyenne) VALUES(?, ?, ?)";
Requête avec des paramètres nommés
Exemple
$sql = "INSERT INTO Etudiants(nom, prenom, moyenne)
VALUES(:nom, :prenom, :moyenne)";
Préparer la requête : $reqprep = $connexion->prepare($sql);
Olivier Mallet (Université de Rouen) PHP 50 / 106
Programmation objet et applications Accès aux bases de données
Exécution d’une requête préparée
Méthode la plus simple : on passe un tableau contenant les valeurs à la
méthode execute de l’objet PDOStatement créé par prepare
Requête avec des points d’interrogation : tableau simple
Exemple
$reqprep->execute(["Dupont", "Jean",10]);
Requête avec des paramètres nommés : tableau associatif
Exemple
$reqprep->execute([":nom"=>"Dupont", ":prenom"=>"Jean",
":moyenne"=>10]);
Olivier Mallet (Université de Rouen) PHP 51 / 106
Programmation objet et applications Accès aux bases de données
Exécution d’une requête préparée (2)
On peut aussi associer les paramètres à des variables avec bindParam
Exemple (Deux exécutions d’une même requête préparée)
$nom = "Dupont";
$prenom = "Jean";
$moyenne = 10;
$reqprep->bindParam(":nom", $nom);
$reqprep->bindParam(":prenom", $prenom);
$reqprep->bindParam(":moyenne", $moyenne);
$reqprep->execute();
$prenom = "Pierre";
$moyenne = 12;
$reqprep->execute();
Olivier Mallet (Université de Rouen) PHP 52 / 106
Programmation objet et applications Accès aux bases de données
Exécution d’une requête préparée : remarques
La méthode execute renvoie un booléen qui indique si la requête a
bien été exécutée
Pour une requête SELECT, c’est aussi sur l’objet $reqprep qu’on
appelle fetch ou fetchAll pour récupérer les résultats
Exemple
$sql = "SELECT moyenne FROM Etudiants";
$sql .= " WHERE prenom = :prenom AND nom = :nom";
$reqprep = $connexion->prepare($sql);
$reqprep->execute([":nom"=>"Dupont", ":prenom"=>"Jean"]);
$moyenne = $reqprep->fetch()["moyenne"];
echo "La moyenne vaut $moyenne";
Olivier Mallet (Université de Rouen) PHP 53 / 106
Programmation objet et applications Accès aux bases de données
Fermeture d’une requête préparée
PHP arrête automatiquement la requête préparée à la fin du script
Mais il peut être intéressant d’arrêter l’interprétation de cette requête
avant, pour libérer des ressources
Pour cela, on supprime l’objet PDOStatement associé à la requête
préparée
Exemple
$reqprep = $connexion->prepare(...);
$reqprep->execute(...);
// traitement éventuel du resultat
unset($reqprep);
Olivier Mallet (Université de Rouen) PHP 54 / 106
Programmation objet et applications Interface DOM de PHP
Interface DOM
Permet de manipuler les documents XML
Créer un objet représentant un document XML :
$doc = new DOMDocument();
Charger un fichier XML : $doc->load("mon_fichier.xml");
Créer une arborescence à partir d’une chaîne de caractères :
Exemple
$xml = "<personne><nom>Dupont</nom><prenom>Jean</prenom>
<ville>Rouen</ville></personne>";
$doc->loadXML($xml);
Olivier Mallet (Université de Rouen) PHP 55 / 106
Programmation objet et applications Interface DOM de PHP
Interface DOM (2)
Enregistrer les données XML d’un DOMDocument dans un fichier :
$doc->save("[Link]");
Renvoyer le contenu du document sous forme d’une chaîne de
caractères : $doc->saveXML();
Les autres fonctions sont identiques à celles de JavaScript (DOM est
un standard du W3C, indépendant des langages)
Les listes d’éléments renvoyées par getElementsByTagName ne sont pas
des tableaux ; on y accède via la méthode item
Exemple (Accès au premier nombre d’un document MathML)
$nombres = $doc->getElementsByTagName("mn");
$premier_nombre = $nombres->item(0);
Olivier Mallet (Université de Rouen) PHP 56 / 106
Programmation objet et applications Interface DOM de PHP
La fonction header
Permet de modifier l’en-tête HTTP de la réponse envoyée par le
serveur PHP
À appeler avant d’afficher la page (comme setcookie ou
session_start ) :
Pas d’instructions echo ou assimilées avant header
Pas de code HTML ou de texte non plus
Applications : redirection, gestion des pages d’erreur, authentification,
génération de fichiers non-HTML
Olivier Mallet (Université de Rouen) PHP 57 / 106
Programmation objet et applications Interface DOM de PHP
DOM : exemple
Exemple (Création d’un fichier SVG représentant un damier de n × n
cases de côté d)
$n = $_GET["n"]; // pour pouvoir paramétrer les dimensions
$d = $_GET["d"];
$couleurs = ["#FFFFFF", "#000000"];
// définition du document et de sa balise racine
$doc = new DOMDocument();
$doc->loadXML("<svg></svg>");
// définition des attributs de <svg>
$svg = $doc->documentElement; // balise racine <svg>
$svg->setAttribute("width", $n * $d);
$svg->setAttribute("height", $n * $d);
$svg->setAttribute("xmlns", "[Link]
Olivier Mallet (Université de Rouen) PHP 58 / 106
Programmation objet et applications Interface DOM de PHP
Suite de l’exemple
Exemple
for ($i = 0 ; $i < $n ; $i++) { // boucle de création des cases
for ($j = 0 ; $j < $n ; $j++) {
$carre = $doc->createElement("rect");
$carre->setAttribute("x", $j * $d);
$carre->setAttribute("y", $i * $d);
$carre->setAttribute("width", $d);
$carre->setAttribute("height", $d);
$carre->setAttribute("style", "fill:".$couleurs[($i + $j) % 2]);
$svg->appendChild($carre);
}
}
header("Content-Type: application/xml"); // le résultat est au format XML
echo $doc->saveXML(); // affichage
Olivier Mallet (Université de Rouen) PHP 59 / 106
Programmation objet et applications Interface DOM de PHP
Résultat pour n = 10 et d = 50
Olivier Mallet (Université de Rouen) PHP 60 / 106
Aspects avancés Manipulation d’images
Manipulation d’images
La bibliothèque GD permet de manipuler des images
3 étapes :
Créer une image (à partir de rien ou d’un fichier JPEG ou PNG)
Effectuer les traitements souhaités
Envoyer l’image au client pour affichage ou l’enregistrer dans un fichier
sur le serveur
Olivier Mallet (Université de Rouen) PHP 61 / 106
Aspects avancés Manipulation d’images
Création d’une image
À partir de rien : imagecreatetruecolor($largeur, $hauteur)
Exemple (Création d’une image vide de 200 pixels × 150 pixels)
$image = imagecreatetruecolor(200, 150);
À partir d’une image existante :
imagecreatefromjpeg($url) si c’est une image au format JPEG
imagecreatefrompng($url) si c’est une image au format PNG
Exemple (On charge l’image images/[Link])
$image = imagecreatefromjpeg("images/[Link]");
Olivier Mallet (Université de Rouen) PHP 62 / 106
Aspects avancés Manipulation d’images
Dessiner des points et des segments
Définir une couleur : imagecolorallocate($image, $rouge, $vert, $bleu)
(composantes RGB entre 0 et 255)
Exemple (On définit la couleur jaune)
$jaune = imagecolorallocate($image, 255, 255, 0);
Dessiner un pixel en (x , y ) : imagesetpixel($image, $x, $y, $couleur)
Exemple (Un pixel jaune de coordonnées (100, 50))
imagesetpixel($image, 100, 50, $jaune);
Dessiner un segment de (x1 , y1 ) à (x2 , y2 ) :
imageline($image, $x1, $y1, $x2, $y2, $couleur)
Exemple (Un segment jaune de (100, 50) à (200, 120))
imageline($image, 100, 50, 200, 120, $jaune);
Olivier Mallet (Université de Rouen) PHP 63 / 106
Aspects avancés Manipulation d’images
Écrire du texte
Écrire le texte txt dans l’image en position (x , y ) (début de la ligne de
base) : imagettftext($image, $taille, $angle, $x, $y, $couleur, $police, $txt) où
$police est le chemin d’accès de la police à utiliser
Exemple (On écrit « Bonjour » horizontalement,
en jaune et en Exmouth 40 au point (50, 120))
imagettftext($image, 40, 0, 50, 120, $jaune,
"polices/[Link]", "Bonjour");
Exemple (Même exemple en inclinant le texte de
30 degrés)
imagettftext($image, 40, 30, 50, 120, $jaune,
"polices/[Link]", "Bonjour");
Olivier Mallet (Université de Rouen) PHP 64 / 106
Aspects avancés Manipulation d’images
Dessiner des ellipses et des cercles
Dessiner une ellipse de centre (x , y ) et de dimensions l × h :
imageellipse($image, $x, $y, $l, $h, $couleur)
Exemple (Une ellipse jaune de centre
(100, 50), de largeur 160 et de hauteur 80)
imageellipse($image, 100, 50, 160, 80, $jaune);
Une ellipse pleine : imagefilledellipse($image, $x, $y, $l, $h, $couleur)
Exemple (La même, mais pleine)
imagefilledellipse($image, 100, 50, 160, 80, $jaune);
Olivier Mallet (Université de Rouen) PHP 65 / 106
Aspects avancés Manipulation d’images
Dessiner des arcs et des secteurs d’ellipse ou de cercle
Un arc de l’ellipse centrée en (x , y ) de dimensions l × h allant de
l’angle d à l’angle f : imagearc($image, $x, $y, $l, $h, $d, $f, $couleur)
Exemple (Le quart inférieur droit de l’ellipse
d’avant)
imagearc($image, 100, 50, 160, 80, 0, 90, $jaune);
Un secteur : imagefilledarc($image, $x, $y, $l, $h, $d, $f, $couleur, $style)
Exemple (Le quart inférieur droit de l’ellipse
pleine d’avant)
imagefilledarc($image, 100, 50, 160, 80, 0, 90,
$jaune, IMG_ARC_PIE);
Angles en degrés dans le sens horaire à partir des x > 0
Olivier Mallet (Université de Rouen) PHP 66 / 106
Aspects avancés Manipulation d’images
Dessiner des rectangles
Dessiner un rectangle dont le coin supérieur gauche est en (x1 , y1 ) et
le coin inférieur droit en (x2 , y2 ) :
imagerectangle($image, $x1, $y1, $x2, $y2, $couleur)
Exemple (Un carré jaune dont les coins sont
en (100, 50) et (190, 140))
imagerectangle($image, 100, 50, 190, 140, $jaune);
Dessiner un rectangle plein :
imagefilledrectangle($image, $x1, $y1, $x2, $y2, $couleur)
Exemple (Le même, mais plein)
imagefilledrectangle($image, 100, 50, 190, 140,
$jaune);
Olivier Mallet (Université de Rouen) PHP 67 / 106
Aspects avancés Manipulation d’images
Dessiner des polygones
Dessiner un polygone à n sommets dont les coordonnées sont
stockées dans le tableau c (sous la forme [x1 , y1 , x2 , y2 , . . .]) :
imagepolygon($image, $c, $n, $couleur)
Exemple (Un triangle jaune dont les sommets
sont en (50, 50), (150, 50) et (100, 100))
imagepolygon($image, [50,50,150,50,100,100],
3, $jaune);
Un polygone plein : imagefilledpolygon($image, $c, $n, $couleur)
Exemple (Le même, mais plein)
imagefilledpolygon($image, [50,50,150,50,100,100],
3, $jaune);
Olivier Mallet (Université de Rouen) PHP 68 / 106
Aspects avancés Manipulation d’images
Autres fonctions
Rendre une couleur transparente (ne fonctionne que si on enregistre
l’image en PNG ou en GIF) : imagecolortransparent($image, $couleur)
Exemple
$image = imagecreatetruecolor(200, 50); // l’image est sur fond noir
$noir = imagecolorallocate($image, 0, 0, 0); // on définit la couleur noire
imagecolortransparent($image, $noir); // maintenant, le fond est transparent
Récupérer les dimensions d’une image :
largeur : imagesx($image)
hauteur : imagesy($image)
Olivier Mallet (Université de Rouen) PHP 69 / 106
Aspects avancés Manipulation d’images
Redimensionner une image
imagecopyresampled($img_dst, $img_src, $x_dst, $y_dst, $x_src, $y_src,
$l_dst, $h_dst, $l_src, $h_src )
prend dans l’image source une zone rectangulaire de dimensions lsrc × hsrc
à la position (xsrc , ysrc ) et la place dans une zone rectangulaire de l’image
de destination de dimensions ldst × hdst à la position (xdst , ydst )
ysrc
xsrc hsrc ydst
source destination
lsrc xdst hdst
ldst
Olivier Mallet (Université de Rouen) PHP 70 / 106
Aspects avancés Manipulation d’images
Redimensionner une image : exemple
$MV = imagecreatefromjpeg("[Link]");
$logo = imagecreatefrompng("[Link]");
imagecopyresampled($MV, $logo, 100, 10, 0, 0, 500, 180, 533, 192);
L’image $MV contient maintenant :
Olivier Mallet (Université de Rouen) PHP 71 / 106
Aspects avancés Manipulation d’images
Exemple plus élaboré : représentation graphique de données
$tab = [12, 28, 15, 37, 8];
$image = imagecreatetruecolor(400, 400);
$blanc = imagecolorallocate($image, 255, 255, 255);
$vert = imagecolorallocate($image, 0, 255, 0);
$rouge = imagecolorallocate($image, 255, 0, 0);
$jaune = imagecolorallocate($image, 255, 255, 0);
$bleu = imagecolorallocate($image ,0, 0, 255);
$couleurs = [$blanc, $vert, $rouge, $jaune, $bleu];
$angle = 0;
for ($i = 0 ; $i < count($tab) ; $i++) {
imagefilledarc($image, 200, 200, 200, 200, $angle, $angle + $tab[$i] * 3.6,
$couleurs[$i], IMG_ARC_PIE);
$angle += $tab[$i] * 3.6;
}
Olivier Mallet (Université de Rouen) PHP 72 / 106
Aspects avancés Manipulation d’images
Résultat
La variable $image contient maintenant ceci :
Mais qu’est-ce qu’on en fait ?
Olivier Mallet (Université de Rouen) PHP 73 / 106
Aspects avancés Manipulation d’images
Envoyer l’image au client
Préciser le type de l’image renvoyée :
header ("Content-type: image/jpeg"); ou
header ("Content-type: image/png"); (à appeler avant les fonctions qui
envoient l’image)
Indiquer, après les traitements, qu’on souhaite envoyer l’image :
imagejpeg($image) ou imagepng($image)
On pourra alors inclure dans une page HTML le fichier PHP comme
une image normale
Exemple (Inclusion dans une page HTML de l’image créée par le
script [Link])
<img src="[Link]" alt="Une image faite en PHP" />
Olivier Mallet (Université de Rouen) PHP 74 / 106
Aspects avancés Manipulation d’images
Enregistrer l’image sur le serveur
imagejpeg($image, $url) ou imagepng($image, $url) après les traitements
Exemple (On enregistre l’image dans le dossier images sous le nom
[Link])
imagepng($image, "images/[Link]");
Pas d’appel à header dans ce cas (on ne renvoie rien)
Olivier Mallet (Université de Rouen) PHP 75 / 106
Aspects avancés Manipulation d’images
Exemple complet
Exemple (On reprend le camembert de tout à l’heure)
header("Content-type: image/png"); // on va renvoyer une image PNG
$tab = [12, 28, 15, 37, 8];
$image = imagecreatetruecolor(400, 400);
$blanc = imagecolorallocate($image, 255, 255, 255);
$vert = imagecolorallocate($image,0, 255, 0);
$rouge = imagecolorallocate($image, 255, 0, 0);
$jaune = imagecolorallocate($image, 255, 255, 0);
$bleu = imagecolorallocate($image, 0, 0, 255);
$couleurs = [$blanc, $vert, $rouge, $jaune, $bleu];
Olivier Mallet (Université de Rouen) PHP 76 / 106
Aspects avancés Manipulation d’images
Exemple complet (suite)
Exemple
$angle = 0;
for ($i = 0 ; $i < count($tab) ; $i++) {
imagefilledarc($image, 200, 200, 200, 200,
$angle,$angle+$tab[$i] * 3.6, $couleurs[$i], IMG_ARC_PIE);
$angle += $tab[$i] * 3.6;
}
imagepng($image); // on renvoie l’image
Olivier Mallet (Université de Rouen) PHP 77 / 106
Aspects avancés Frameworks PHP
L’architecture Modèle-Vue-Contrôleur (MVC)
3 composants
Modèle : gère l’état de l’application (variables de session, fichiers,
bases de données)
Vue : présente les données à l’utilisateur dans une page
Contrôleur : reçoit les requêtes envoyées par l’utilisateur
Olivier Mallet (Université de Rouen) PHP 78 / 106
Aspects avancés Frameworks PHP
Code simpliste pour l’affichage des billets d’un blog
<!DOCTYPE html>
<?php
$connexion = new PDO("mysql:host=localhost;dbname=blog", "usr", "mdp");
$resultat = $connexion->query(’SELECT id, titre FROM billets’); ?>
<html>
<head><title>Liste des billets</title></head>
<body>
<h1>Liste des billets</h1>
<ul>
<?php while ($ligne = $resultat->fetch()) { ?>
<li><a href="/[Link]?id=<?php echo $ligne[’id’]; ?>">
<?php echo $ligne[’titre’]; ?></a></li>
<?php }
$connexion = null;?>
</ul>
</body>
</html>
Olivier Mallet (Université de Rouen) PHP 79 / 106
Aspects avancés Frameworks PHP
Inconvénients du code précédent
Aucun contrôle d’erreurs : rien n’est prévu si la connexion à la base de
données échoue
Code mal organisé : la maintenance deviendra de plus en plus difficile
si on ajoute des fonctionnalités (traitement de formulaire, validation
des données, envoi de mails. . .)
Impossible de réutiliser du code pour d’autres parties du blog : tout
est dans le même fichier
Olivier Mallet (Université de Rouen) PHP 80 / 106
Aspects avancés Frameworks PHP
Séparation logique - vue : logique ([Link])
$connexion = new PDO("mysql:host=localhost;dbname=blog", "usr","mdp");
$resultat = $connexion->query(’SELECT id, titre FROM billets’);
$billets = [];
while ($ligne = $resultat->fetch()) {
$billets[] = $ligne;
}
$connexion = null;
// on inclut la vue
require ’gabarits/[Link]’;
Olivier Mallet (Université de Rouen) PHP 81 / 106
Aspects avancés Frameworks PHP
Séparation logique - vue : vue (gabarits/[Link])
<!DOCTYPE html>
<html>
<head><title>Liste des billets</title></head>
<body>
<h1>Liste des billets</h1>
<ul>
<?php foreach ($billets as $billet) { ?>
<li>
<a href="/[Link]?id=<?php echo $billet[’id’]; ?>">
<?php echo $billet[’titre’]; ?>
</a>
</li>
<?php } ?>
</ul>
</body>
</html>
En modifiant cette vue, on peut exporter les billets dans un autre format
Olivier Mallet (Université de Rouen) PHP 82 / 106
Aspects avancés Frameworks PHP
Séparation modèle - contrôleur : le modèle ([Link])
function connexion_base_de_donnees(){
$connexion = new PDO("mysql:host=localhost;dbname=blog", "usr",
"mdp");
return $connexion;
}
function deconnexion_base_de_donnees(&$connexion){
connexion = null;
}
(à suivre. . .)
Olivier Mallet (Université de Rouen) PHP 83 / 106
Aspects avancés Frameworks PHP
Séparation modèle - contrôleur : suite du modèle
function liste_billets(){
$connexion = connexion_base_de_donnees();
$resultat = $connexion->query(’SELECT id, titre FROM billets’);
$billets = [];
while ($ligne = $resultat->fetch()) {
$billets[] = $ligne;
}
deconnexion_base_de_donnees($connexion);
return $billets;
}
On peut maintenant réutiliser les fonctions dans une autre page du blog.
Olivier Mallet (Université de Rouen) PHP 84 / 106
Aspects avancés Frameworks PHP
Séparation modèle - contrôleur : le contrôleur ([Link])
require_once ’[Link]’;
$billets = liste_billets();
require ’gabarits/[Link]’;
Le contrôleur extrait les données du modèle et appelle la vue pour les
mettre en forme.
Olivier Mallet (Université de Rouen) PHP 85 / 106
Aspects avancés Frameworks PHP
Créer un squelette de page réutilisable
(gabarits/mise_en_page.php)
<!DOCTYPE html>
<html>
<head>
<title><?php echo $titre; ?></title>
</head>
<body>
<?php echo $contenu; ?>
</body>
</html>
Olivier Mallet (Université de Rouen) PHP 86 / 106
Aspects avancés Frameworks PHP
Utiliser le squelette pour simplifier la vue
(gabarits/[Link])
<?php $titre = ’Liste des billets’;
ob_start(); // ce qui suit ne s’affiche pas mais est mis dans un tampon
?>
<h1>Liste des billets</h1>
<ul>
<?php foreach ($billets as $billet) { ?>
<li>
<a href="/[Link]?id=<?php echo $billet[’id’]; ?>">
<?php echo $billet[’titre’]; ?>
</a>
</li>
<?php } ?>
</ul>
<?php $contenu = ob_get_clean();
// la fonction ob_get_clean lit le contenu du tampon puis l’efface
include ’mise_en_page.php’; ?>
Olivier Mallet (Université de Rouen) PHP 87 / 106
Aspects avancés Frameworks PHP
Afficher un billet repéré par son identifiant
On ajoute une nouvelle fonction dans [Link] :
function infos_billet($id) {
$connexion = connexion_base_de_donnees();
$requete = ’SELECT date, titre, corps FROM billets WHERE id = :id’;
$reqprep = $connexion->prepare($requete);
$reqprep->bindParam(":id", $id);
$reqprep->execute();
$ligne = $reqprep->fetch();
deconnexion_base_de_donnees($connexion);
return $ligne;
}
Olivier Mallet (Université de Rouen) PHP 88 / 106
Aspects avancés Frameworks PHP
Contrôleur pour la page d’affichage d’un billet
([Link])
require_once ’[Link]’;
$billet = infos_billet($_GET[’id’]);
require ’gabarits/[Link]’;
Olivier Mallet (Université de Rouen) PHP 89 / 106
Aspects avancés Frameworks PHP
Vue pour la page d’affichage d’un billet
(gabarits/[Link])
<?php $titre = $billet[’titre’];
ob_start();
?>
<h1><?php echo $billet[’titre’]; ?></h1>
<div class="date"><?php echo $billet[’date’]; ?></div>
<div class="corps">
<?php echo $billet[’corps’]; ?>
</div>
<?php $contenu = ob_get_clean();
include ’mise_en_page.php’;
?>
Olivier Mallet (Université de Rouen) PHP 90 / 106
Aspects avancés Frameworks PHP
Avantages et inconvénients de cette organisation
Avantages :
Très facile de créer une nouvelle page
Pas de code dupliqué
Inconvénients :
Le site va planter si id est absent ou invalide
Chaque contrôleur doit inclure [Link]. . . et si on avait besoin
d’inclure d’autres fichiers partout ?
Mieux vaut centraliser les tâches globales (sécurité, chargement de la
configuration, routage des requêtes. . .) pour ne pas oublier d’inclure un
fichier
Olivier Mallet (Université de Rouen) PHP 91 / 106
Aspects avancés Frameworks PHP
Solution : un contrôleur frontal
Contrôleur frontal : fichier PHP par lequel passent toutes les requêtes
Sans contrôleur frontal :
Afficher la liste des billets : /[Link]
Afficher un seul billet : /[Link]
Avec le contrôleur frontal [Link] :
Afficher la liste des billets : /[Link]
Afficher un seul billet : /[Link]/billet
[Link] est toujours appelé et dirige la requête en fonction de
l’URL
Olivier Mallet (Université de Rouen) PHP 92 / 106
Aspects avancés Frameworks PHP
Le contrôleur frontal ([Link])
// on inclut les ressources nécessaires
require_once ’[Link]’;
require_once ’[Link]’;
// on dirige la requête
$uri = parse_url($_SERVER[’REQUEST_URI’], PHP_URL_PATH);
if (’/[Link]’ === $uri) {
action_liste();
}
elseif (’/[Link]/billet’ === $uri && isset($_GET[’id’])) {
action_billet($_GET[’id’]);
}
else {
header(’HTTP/1.1 404 Not Found’);
echo ’<html><body><h1>Page introuvable</h1></body></html>’;
}
Olivier Mallet (Université de Rouen) PHP 93 / 106
Aspects avancés Frameworks PHP
Les contrôleurs ([Link])
function action_liste() {
$billets = liste_billets();
require ’gabarits/[Link]’;
}
function action_billet($id) {
$billet = infos_billet($id);
require ’gabarits/[Link]’;
}
Olivier Mallet (Université de Rouen) PHP 94 / 106
Aspects avancés Frameworks PHP
Avantages et inconvénients de cette nouvelle organisation
Avantages :
On peut centraliser certaines fonctionnalités
URL flexibles
Code facilement réutilisable
Inconvénients :
Routage pas parfait (Apache permet d’écrire / au lieu de /[Link]
mais le contrôleur frontal ne comprendrait pas)
On passe beaucoup de temps sur l’architecture plutôt que sur
l’application elle-même
On va encore devoir passer du temps sur le traitement de formulaires,
la validation des champs, la journalisation, sécurité. . .⇒ éviter de
réinventer la roue
Un framework PHP permet d’éviter ces inconvénients tout en gardant
les avantages !
Source de cette partie : [Link]
Olivier Mallet (Université de Rouen) PHP 95 / 106
Aspects avancés Frameworks PHP
Quelques frameworks PHP
CakePHP ([Link]
CodeIgniter ([Link]
Laravel ([Link]
Symfony ([Link])
Zend Framework ([Link]
Olivier Mallet (Université de Rouen) PHP 96 / 106
Quelques remarques sur la sécurité
Qu’est-ce que la sécurité ?
Préoccupations du gestionnaire de l’application :
disponibilité et bon fonctionnement de l’application
non-divulgation des données confidentielles
intégrité des données
intégrité du site et de son image
Préoccupations de l’utilisateur :
disponibilité des données sans interruption
non-divulgation de ses données personnelles
intégrité de ses données personnelles
non-détournement de son identité et de son image
Il peut y avoir conflit entre les deux → à trancher par le développeur
Risque juridique et d’image
Olivier Mallet (Université de Rouen) PHP 97 / 106
Quelques remarques sur la sécurité
Remarques générales
Ne pas attendre la fin d’un projet pour se préoccuper de la sécurité
Mettre à jour l’interpréteur PHP et le serveur web et les configurer
correctement
Olivier Mallet (Université de Rouen) PHP 98 / 106
Quelques remarques sur la sécurité
Sécurité des accès aux fichiers
Stocker les fichiers dans un dossier qui n’est pas atteignable par le
web (sauf ceux qui doivent être directement appelés par HTTP)
Les répertoires et fichiers ne devraient être accessibles qu’en lecture
(sauf nécessité)
Configurer le serveur pour interdire l’accès direct à certains fichiers
(par exemple ceux dont le nom commence par un préfixe particulier)
Masquer les extensions pour ne pas dévoiler trop d’informations sur le
fonctionnement du serveur
Olivier Mallet (Université de Rouen) PHP 99 / 106
Quelques remarques sur la sécurité
Vérifier les entrées en provenance des utilisateurs
Toujours vérifier les informations envoyées par l’utilisateur
Définir précisément les critères de validité des données (taille, type,
caractères autorisés, valeurs possibles, format. . .) et les vérifier
Le cas par défaut d’un if... else ou d’un switch ne soit pas être l’une
des valeurs possibles, mais le cas « impossible »
L’extension Filter permet de valider et filtrer les données (voir
[Link]
Pour éviter les problèmes dus aux conversions implicites :
Vérifier la valeur mais aussi le type des variables
Si une valeur doit avoir un certain type, faire la conversion avant
d’utiliser cette valeur
Utiliser autant que possible le === plutôt que le ==
Demander à l’utilisateur de ressaisir les informations importantes
(email, mot de passe. . .)
Olivier Mallet (Université de Rouen) PHP 100 / 106
Quelques remarques sur la sécurité
Éviter les attaques les plus courantes
Injection SQL :
Méthode quote de l’objet PDO qui protège la chaîne de caractères
passée en argument
Requêtes préparées (à privilégier : plus portables et plus rapides)
XSS (Cross Site Scripting) :
Exemple : un pirate poste sur un forum un message qui contient du
code JavaScript dans une balise <script>. . .
. . . puis un visiteur du forum lit ce message et subit une attaque (vol
du cookie de session, redirection non souhaitée. . .)
Solution classique : utiliser htmlspecialchars($chaine) qui convertit
dans $chaine les caractères &, ", ’, < et > en entités HTML
Exemple
Si $_POST["var"] vaut "<a href=’[Link]’>Lien</a>",
htmlspecialchars($_POST["var"]) vaudra
"<a href='[Link]'>Lien</a>"
Olivier Mallet (Université de Rouen) PHP 101 / 106
Quelques remarques sur la sécurité
Emplacement des contrôles
Ne pas stocker un résultat chez l’utilisateur si on veut pouvoir
l’utiliser en confiance
On peut stocker les paramètres du calcul chez le client et refaire le
calcul en interne. . .
. . . ou stocker le résultat dans une variable de session si le calcul
prend du temps
Dans un formulaire en plusieurs étapes, ne pas réinjecter les données
saisies précédemment sans vérification
Vérifier les données client ne dispense pas de les vérifier côté serveur
Attention aux hypothèses hasardeuses !
Ne pas compter sur la protection par le secret
Olivier Mallet (Université de Rouen) PHP 102 / 106
Quelques remarques sur la sécurité
Sécurité des sessions
On peut usurper l’identité d’un utilisateur si on connaît son identifiant
de session
Désactiver la transmission de l’identifiant dans l’URL (directives
session.use_trans_sid et session.use_only_cookies dans le
fichier [Link])
Protection (pas absolue) contre le vol de session :
stocker à la création de la sessions des infos sur le client (adresses IP
publique et privée, navigateur utilisé. . .)
vérifier à chaque ouverture de session que ces infos n’ont pas changé
Protection contre la fixation de session (attribution à l’utilisateur d’un
identifiant de session par l’attaquant) :
calculer un nouvel identifiant de session quand l’utilisateur s’identifie
pour ça, appeler la fonction session_regenerate_id(); après
session_start dans le code qui gère le formulaire de login
Olivier Mallet (Université de Rouen) PHP 103 / 106
Quelques remarques sur la sécurité
Gestion des erreurs
Dans le fichier de configuration [Link], mettre la directive
display_errors à Off lors du déploiement (pour éviter de donner
aux pirates des informations sur l’organisation du site ou sur le
serveur de bases de données). . .
. . . mais la laisser à On lors du développement pour mettre en
évidence les problèmes
Activer la directive log_errors pour garder une trace des erreurs
La fonction error_log permet d’enregistrer manuellement des
informations dans un fichier journal ou de les envoyer par mail
Remarque
La fonction error_log n’interfère pas avec les fonctions telles que
session_start (contrairement à echo )
Le fichier journal ne doit pas être accessible en ligne !
Olivier Mallet (Université de Rouen) PHP 104 / 106
Quelques remarques sur la sécurité
Sécurité des bases de données
Un script PHP ne doit pas se connecter au serveur de bases de
données en tant que propriétaire de la base ou administrateur
Créer différents utilisateurs pour l’application avec des droits limités
et adaptés à chaque cas d’utilisation
Stocker les données sensibles (mots de passe. . .) sous forme cryptée à
l’aide de la fonction PHP password_hash
La fonction password_verify permet de vérifier la correspondance entre
un mot de passe en clair et un mot de passe crypté
Olivier Mallet (Université de Rouen) PHP 105 / 106
Quelques remarques sur la sécurité
Bonnes habitudes
Vérifier la cohérence des résultats (positivité, ordre de grandeur,
précision. . .) pour détecter des problèmes
Analyser régulièrement les statistiques de l’application et les logs du
serveur
Ne jamais faire confiance à l’utilisateur même dans une application
intranet
Définir des contrôles d’accès stricts pour éviter des attaques ou
réduire leurs conséquences
Ne pas complexifier inutilement le code sous prétexte de sécurité
Se former sur la sécurité et former son équipe
Faire relire le code par une personne extérieure à l’équipe de
développement
Olivier Mallet (Université de Rouen) PHP 106 / 106