COURS
PHP5 Avancé
& MVC
DIFFUSION : Étudiants Master Langages et technologies du Web
1 Pré requis ................................................................................................................................................... 3 2 Objectif du cours ....................................................................................................................................... 3 3 Le développement d'applications web, un développement complexe .................................................... 4
4 Développement web ................................................................................................................................. 5 5 Modèle-Vue-Contrôleur (MVC) ................................................................................................................. 6
6 MVC et PHP : implémentation .................................................................................................................. 8
6.1 Architecture des dossiers.................................................................................................................... 8
6.2 Contrôleur : ......................................................................................................................................... 9 6.3 Modèle : ............................................................................................................................................ 10
6.4 Vue : .................................................................................................................................................. 10
7 Programmation orientée objet en PHP5 ................................................................................................. 11
7.1 Rappel ............................................................................................................................................... 11
7.2 Classe et instance. ............................................................................................................................. 12
7.3 Copie, Héritage, redéfinition et subtilités. ....................................................................................... 14
7.3.1 Copie & référence ...................................................................................................................... 14
7.3.2 Héritage ..................................................................................................................................... 15
7.3.3 Surcharge ou redéfinition .......................................................................................................... 17
7.3.4 Subtilités .................................................................................................................................... 18
8 Base de données via PDO ........................................................................................................................ 23
8.1 Driver et installation ......................................................................................................................... 25
8.2 Connexion et gestion d'erreur de la connexion ............................................................................... 26
8.2.1 Connexion .................................................................................................................................. 26
8.2.2 Erreurs de connexion ................................................................................................................. 26
8.3 Requêtes et traitements ................................................................................................................... 27
8.3.1 Requêtes .................................................................................................................................... 27
8.3.2 Traitements................................................................................................................................ 28
9 Template et Vue ...................................................................................................................................... 30
9.1 Principe du Template ........................................................................................................................ 30
9.2 Exemple « fait maison » : .................................................................................................................. 31
9.2.1 Fichier de présentation ............................................................................................................. 31
9.2.2 Script de données ...................................................................................................................... 31
9.2.3 Moteur du Template ................................................................................................................. 31
9.2.4 Sortie HTML. .............................................................................................................................. 32
9.3 Smarty : Gestionnaire de Template .................................................................................................. 33
10 Gestion des Erreurs ................................................................................................................................. 34
10.1 Gestion d'erreurs – Kit de survie ................................................................................................... 34
10.1.1 ........................................................................................................................................ 35
10.1.2 Dans vos script ........................................................................................................................... 36
10.2 Les assertions ................................................................................................................................ 37
10.3 Les Exceptionsk ............................................................................................................................. 38
10.3.1 Principe ...................................................................................................................................... 38
10.3.2 Usage ......................................................................................................................................... 39
11 Développement et sécurité ..................................................................................................................... 40
11.1 Les points clés ................................................................................................................................ 40
11.2 Tout le monde ment ! ................................................................................................................... 40
11.2.1 Ne fait pas confiance au utilisateur. .......................................................................................... 40
11.2.2 Injection SQL .............................................................................................................................. 41
11.2.3 Session – Cookies et sécurité. ................................................................................................... 43
11.2.4 Vérifier vos logs ......................................................................................................................... 44
Historique des révisions
Version | Auteur | Commentaires | Date |
1 | Frédéric Théron | Création du document | 26/01/2012 |
- Cours PHP de Jacques Bandet
-Cours HTML et XHTML de Jacques Bandet
L'objectif du cours est de vous donner une méthode de développement web (MVC), et de présenter des fonctions avancées en PHP5 pour une utilisation 'professionnelle'.
Le développement d'applications web est complexe, on peut travailler pour des cibles multiples :
? Cibles machines (serveur, station client, Smartphone, Tablet …)
? Cibles browsers (IE 6et+, Chrome, Firefox, Safari, Opéra…)
Le développement d'applications web est complexe, on doit travailler avec de multiples langages :
? Langages coté serveur web [ASP,PHP,Python,Perl …]
? Langages coté client [Javascript,Vbscript]
? Langages de balisage [HTML, CSS]
Le développement d'applications web est complexe, on doit travailler pour de multiples publics:
? Utilisateur débutant
? Utilisateur confirmé
? Gestionnaire des données
? Administrateur de l'application
Le développement d'applications web est complexe, car on est soumis à des contraintes :
? Contraintes de sécurités
? Contraintes d'intégrité des données.
? Contraintes légales
Quand on débute en développement web, on mélange souvent les langages de script, de balisage, de CSS dans un seul fichier :
On a dans ce bout de code, les erreurs majeures de programmation et de logique :
? HTML, CSS, PHP dans un même document.
? Pas de commentaires
? Pas de bloc logique – d'indentation
? Copier-coller incohérent
? Formulaire pas compréhensible (Oui à quoi ?)
Q : Comment maintenir ce code ?
En développement logiciel, il existe des architectures de développement (architectural pattern) dont le but est d'isoler le domaine logique de la partie IHM.
? | Une architecture de développement ? Modèle conceptuel |
Architecture de développement => Organisation logicielle de l'application. [Modèle programmeur]
Modèle conceptuel => Organisation des fonctionnalités de l'application. [Modèle utilisateur]
On trouve MVC dans des travaux datant de 1979 par un groupe de travail Xerox Parc.
Les ingénieurs ont théorisé MVC pour le langage Smalltalk (langage objet, de haut niveau d'abstraction).
Le but de MVC est la séparation de l'application en trois couches :
? Le Modèle décrit les actions, les traitements métiers de l'application (connexion aux données, algo de résolution, vérification, sécurité…).
? La Vue est la partie restitution des données aux utilisateurs de l'application (HTML, PDF, XML…)
? Le Contrôleur est une interface entre la vue et le modèle. [Le mot interface ici ne doit pas être confondu avec l'interface utilisateur ou interface de classe]
Représentation MVC pour une application WEB.
MVC et MVC2 :
Dans une architecture MVC, il peut exister plusieurs vues, plusieurs modèles mais aussi plusieurs contrôleurs.
Dans une architecture MVC2, il n'existe plus qu'un seul et unique contrôleur réceptionnant toutes les requêtes clientes.
Avantages et inconvénients de ce type de modèle.
Avantage :
? Modularités.
? Maintenance.
? Gestion multi-développeurs.
? L'isolation
Inconvénients :
? Complexité de communication entre composants.
? Apprentissage notamment dans le cadre d'un Framework.
L'implémentation dans une application web est simple dès lors que l'on a bien préparé l'analyse de l'application.
La mise en place d'une structure de dossier permet d'appréhender plus facilement l'implémentation du MVC.
On voit le principe d'une page de distribution/dispatch () Pour utiliser proprement le modèle MVC, on peut utiliser un dispatcher, une page où toutes les requêtes arrivent et sont aiguillées. Exemple : ?do=connexion => Paramètre d'aiguillage dans l'URL (GET) |
Sur une application importante, on risque d'avoir un énorme Switch ce qui n'est ni élégant, ni pertinent. On peut travailler avec un dispatcher générique qui appel directement le contrôleur. On peut aussi avoir un appel à un unique contrôleur avec l'action en paramètre. |
6.2Contrôleur :
Le contrôleur reçoit les requêtes de l'utilisateur et fait l'intermédiaire entre le modèle et la vue pour répondre aux requêtes.
Scénario :
On a une demande de validation de connexion à une application avec Login et Password.
On va faire une demande au contrôleur pour gérer cette connexion.
Le contrôleur va appeler le modèle de gestion des utilisateurs et retourner une information indiquant si la personne peut ou ne pas se connecter. Il appelle la vue avec le retour indiqué par le modèle pour la présentation à l'utilisateur.
Page web Lors de la validation : ?do=connexion |
Page (dispatcher) On inclut le contrôleur et selon la demande, on appel la fonction du contrôleur. A Savoir : Même si le contrôleur peut être de type fonction dans la majorité des cas, ce sera une classe. |
Page On voit bien l'interface avec le modèle et avec la vue. Il y a bien isolation entre le modèle et la vue. |
6.3 Modèle :
On parle de Modèle pour la partie métier de l'application.
On a les scripts d'actions de l'application : , …
On doit avoir dans le modèle, les classes, les fonctions, les fichiers de paramètres …
? | On n'a pas et on ne doit pas avoir d'élément visuel dans le modèle sauf lors du développement, pour le debug. | |
6.4 Vue :
La vue est un ou plusieurs composants gérant la présentation. Ce peut être directement des fichiers HTML, mais aussi des fichiers textes, ou d'autres formats XML, PDF…
Le principe MVC est de dissocier les données et la présentation. La vue doit représenter un visuel (graphisme de l'application Web) et les données traitées par le modèle.
On a deux possibilités pour résoudre ce problème :
? Créer des pages HTML avec du PHP.
Si on code avec ce système, on ne doit jamais utiliser de fonctions PHP pour créer la donnée. Les seules fonctions acceptables sont : echo(); print();
? Utiliser un système de Template.
On verra le système de Template, plus longuement dans le chapitre 9
Quand on développe pour le web, on utilise souvent du JavaScript ou de l'AJAX. La question est de savoir | |
ou mettre proprement les appels à AJAX ? |
La programmation par objets ou par procédures classiques sont deux paradigmes du développement. La programmation orientée objet comporte les avantages suivants :
? un code réutilisable.
? un code modulaire.
? un code compréhensible.
? Un code conceptuel.
Qu'est-ce qu'une classe ?
Une classe est un modèle de définitions pour la création d'objets.
Une classe définit les attributs de l'objet (des champs) et des méthodes (des fonctions).
Par analogie : le plan d'une maison n'est pas une maison mais c'est le moyen de créer une ou plusieurs maison(s).
Qu'est-ce qu'un objet ?
Concrètement, un objet est une instance d'une classe.
Par analogie : La maison est une instance faite à partir du plan de la maison.
? | CLASSE ? OBJET |
7.2Classe et instance.
Déclaration d'une classe : | Instanciation d'un objet : |
La sureté de l'application :
public : L'accessibilité à la méthode ou à l'attribut est possible de toute l'application. Par défaut si aucun type d'accès n'est indiqué c'est un accès public. protected : L'accessibilité à la méthode ou à l'attribut est possible à la classe qui l'a défini mais aussi à ses classes héritées. private : L'accessibilité à la méthode ou à l'attribut est possible uniquement à la classe. |
Constructeur et Destructeur :
PHP propose un moyen d'initialisation d'un objet au moment de sa création grâce à : __construct (){} Lors de l'instanciation par le mot clé NEW si dans la class la méthode __construct existe, elle va être appelée.
PHP propose un moyen de supprimer un objet grâce à __destruct(){}. Cette méthode est automatiquement appelée quand l’objet est détruit, soit par delete() ou unset(), soit à la fin du script. Un destructeur est pratique pour fermer les ressources ouvertes : fichiers, connexions vers des serveurs de bases de données, etc.
Exemple
Définition de la classe :
Usage de la classe :
$this: (comme en Java)
Il est souvent utile de pouvoir faire référence à l’objet en cours dans une méthode. C’est par exemple le cas pour accéder à un attribut ou lancer une autre méthode. La méta variable $this est une référence permanente vers l’objet courant.
Accès au méthode et attribut (? JAVA):
En java pour accéder à une méthode ou un attribut, on utilise nom_objet . nom_attribut
En PHP, pour accéder à une méthode ou un attribut, on utilise $nom_objet -> nom_attribut
? Il n'y a pas $ devant nom_attribut |
7.3Copie, Héritage, redéfinition et subtilités.
Il faut définir la différence entre deux objets qui sont « identiques» et deux objets qui sont « les mêmes ».
Ex : 2 DVD du même film dans la même collection sont identiques mais ne sont pas les mêmes.
La classe Sortie web : | Le script |
Par défaut en PHP5, l'assignation est une référence.
$obj1 = $obj2 // on ne copie pas l'objet on créait une référence (le & est implicite) (rappel contraire Jacques Bandet. PHP4-PHP5)
Si on veut réellement créer une copie de l'objet, on utilise la fonction clone() qui copie l'objet.
L'héritage est la création de classe à partir d'une autre classe.
Ex : mon objet ma_ferrari provient de la class voiture qui est héritée de la class véhicule_a_moteur.
? PHP5 ne supporte pas l'héritage multiple (?JAVA) |
Prototype de l'héritage en PHP5:
Class nom_new_classe extends nom_classe_herité {
}
L'héritage dans PHP5 est un héritage strict.
Père | Fils | |
Paramètre obligatoire | w | x < w à condition de créer des valeurs par défaut. |
Paramètre optionnel | y | z>y |
Les méthodes de la classe fils doivent avoir des prototypes compatibles avec ceux de la classe père.
Il est possible d’ajouter des paramètres supplémentaires, à condition qu’ils soient facultatifs. Il est aussi possible de rendre facultatifs des paramètres en leur donnant une valeur par défaut.
Pour résumer, le nombre de paramètres obligatoires de la méthode fille doit être inférieur ou égal au nombre de paramètres possibles de la méthode mère ; le nombre de paramètres possibles de la méthode fille doit quant à lui être supérieur ou égal au nombre de paramètres possibles de la méthode mère.
Par exemple, une méthode qui a trois paramètres obligatoires sur cinq peut être remplacée par une méthode qui a un paramètre obligatoire (nombre inférieur) et cinq facultatifs (donc six au total, ce qui est supérieur aux cinq initiaux).
Seuls les constructeurs ne sont pas soumis à cette règle car la notion de constructeur générique n’a pas vraiment de sens.
On créait une classe héritée de la classe compte vue précedement. On créait une classe bourse qui étend les attributs et les méthodes de notre classe compte. |
On va utiliser cette classe :
La sortie web :
Dans la définition de l'héritage strict, on parle implicitement de la surcharge de méthode ou d'attribut.
On peut dans la classe fille, redéfinir une méthode ou un attribut. Dans ce cas, par défaut, c'est la dernière définition qui est utilisée.
Cependant, on peut vouloir accéder aux méthodes parentes, on utilise alors la notation statique:
Parent::methode()
A savoir : L'accès statique est possible dans un script, attention si la méthode a besoin d'un objet ($this) alors une erreur est déclenchée.
Class Parent Class Fille
Script : Sortie Web :
? Héritage et redéfinition des contrôles d'accès.
Si vous redéfinissez une méthode ou un attribut, vous pouvez changer alors sa sécurité d'accès. Le principe est simple, vous ne pouvez restreindre un contrôle d'accès.
Tableau des comportements d'héritages :
Classe père | Classe fils | |
Attributs ou méthodes | Public | Public |
Protected | Protected , public | |
Private | Private, Protected , public |
Attention :
On ne peut pas redéfinir une méthode privée. Si on le faisait, on créerait en réalité une nouvelle méthode. Si vous redéfinissez une méthode privée, PHP5 considérera qu’il a deux méthodes de même nom simultanément dans la classe. Si c’est une méthode de la classe mère qui y fait appel, elle accédera à la méthode privée initiale. Si inversement c’est une méthode de la classe fille qui y fait appel, elle accèdera à la nouvelle implémentation.
? Il est déconseillé de redéfinir une méthode privée |
? Classe abstraites et interfaces
Une classe abstraite c'est une implémentation minimale d'une classe.
Elle définit les méthodes qui devront être obligatoire pour la classe qui hérite de la classe abstraite.
Les interfaces (Attention : on parle ici d'interface au sens développement) permettent de créer du code qui spécifie quelles méthodes une classe doit implémenter. Toutes les méthodes déclarées dans une interface doivent être publiques.
Intérêt :
Les interfaces peuvent être vues comme des contrôles de qualité (vérifier que les objets correspondent bien aux spécifications) et les classes abstraites comme des implémentations incomplètes, à finir.
Déclaration class abstraite | Déclaration interface |
Implémentation de classe abstraite | Implémentation d'une interface |
A savoir o Une classe peut implémenter plusieurs interfaces en même temps.
o Une classe ne peut pas avoir d'héritage multiple classe abstraite ou pas.
o On ne peut pas surcharger une interface ou une méthode abstraite (intérêt même de ces systèmes)
? Il est déconseillé d'utiliser classe abstraite et interface. On utilise soit l'une ou l'autre des méthodes. | ||
? Fonction finales
Le concept de méthodes finales est simple, on indique à PHP5 qu'aucune classe dérivée n'a le droit de modifier l'implémentation d'une méthode.
Ex : On gère une collection de média, on a une classe media duquel on dérive pour créer la classe DVD, BD, CD …
Si dans la class média, on créait une méthode perdu($ref_media); on ne veut pas pouvoir surcharger cette méthode. |
On peut aussi déclarer une classe comme final, mais alors on ne pourra plus hériter d'elle. L'intérêt est là plus limité.
? Fonctions particulières
Fonction de clonage :
On a vu le principe du clonage, on peut créer manuellement une fonction de clonage qui viendra s'ajouter au principe natif de PHP5
Fonction d'appel à une méthode (utile pour le débug) :
Cette méthode intercepte tous les appels à des méthodes qui n'existent pas.
Fonction d'information
La fonction get_class retourne une chaine donnant le nom de la classe de l'objet. |
Classe d'information
Il existe une classe ReflectionClass("Nom_classe") ayant des méthodes d'information sur la classe.
Ex : Avec la classe bourse
La sortie web donne
On peut aussi avoir la vue de la classe
On aura en sortie web :
? Chargement de classe
Comme dans tout langage objet, on doit charger les classes que l'on va utiliser.
Les fichiers sont inclus suivant le chemin du fichier fourni.
Si aucun n'est fourni, l'include_path sera vérifié.
Si le fichier n'est pas trouvé dans l' include_path alors include() vérifiera dans le dossier du script appelant et dans le dossier de travail courant avant d'échouer.
Si l'instruction et _once, PHP vérifie si le fichier a déjà été inclus et si c'est le cas, ne l'inclut pas une deuxième fois.
L'instruction include() enverra une erreur de type warning si elle ne peut trouver le fichier; ce comportement est différent de require(), qui enverra une erreur de type fatal.
Pour ne pas à chaque fois utiliser l'adresse exacte du fichier à inclure, on peut utiliser la variable magique __FILE__.
? | On utilise require() quand on gère des classes |
L'extension PHP Data Object (PDO) définit une interface pour accéder à une base de données depuis PHP.
PDO fournit une interface d'abstraction à l'accès de données, ce qui signifie que vous utilisez les mêmes fonctions pour exécuter des requêtes ou récupérer les données quelle que soit la base de données utilisée.
PDO ne fournit pas une abstraction de base de données : il ne réécrit pas le SQL, n'émule pas des fonctionnalités manquantes. Vous devriez utiliser une interface d'abstraction complète si vous avez besoin de cela.
PDO n'est disponible qu'avec PHP5 car PDO utilisent les notions OO de PHP5.
Tableau des drivers et des bases de données () :
|
|
Pour installer un driver :
On modifie le fichier (fichier de paramètre existant sous Windows et linux), ou on utilise la fonction dl()pour les charger au moment de l'exécution.
Sous windows:
; ; ; ;
Sous linux les extensions sont des .so
Pour se connecter à une base de données, il faut tout d'abord créer une instance de la classe PDO.
Le constructeur PDO à besoin de 3 paramètres :
1 - DSN (Data Source Name).
2- Le nom d’utilisateur.
3- Le mot de passe.
Le DSN dépend du driver de la base de données.
Le Data Source Name (DSN) de PDO_MYSQL est composé des éléments suivants :
• host : adresse du serveur distant (nom ou adresse IP, « localhost » pour un serveur local) ;
• dbname : nom de la base de données à utiliser ;
• port : donnée facultative indiquant le port TCP/IP utilisé pour la connexion ;
• unix_socket : donnée facultative indiquant l’adresse du socket unix pour la connexion locale.
Les erreurs de connexion peuvent provenir de plusieurs facteurs :
? Le pilote n'a pas été chargé
? La base de données n'a pas été trouvée ? Le login et mot de passe ne sont pas corrects.
? …
La classe PDO gère les exceptions et donc lèvera automatiquement une exception.
Comme en JAVA, la structure de gestion des exceptions est :
Implémentation pour les erreurs de connexions :
Pour envoyer des requêtes au serveur, on a deux méthodes de l'objet PDO :
? Exec() ? utiliser pour les requêtes INSERT, UPDATE, DELETE.
Cette méthode renvoie le nombre de lignes modifiés.
? Query() ? uiliser pour les requêtes SELECT, SHOW, DESC, EXPLAIN.
Cette méthode renvoie un objet PDOStatement comprenant les résultats de la requête.
Par Exemple :
La méthode query() renvoi un objet de type PDOStatement.
Il faut donc utiliser sur le résultat, des méthodes pour récupérer les données :
? fetch() ?Permet d'accéder aux résultats séquentiellement (on utilise while par exemple).
mixed PDOStatement::fetch ([ int $fetch_style [, int $cursor_orientation= PDO::FETCH_ORI_NEXT [, int $cursor_offset= 0 ]]] )
? fetchAll() ? retourne l'ensemble des données dans un tableau.
array PDOStatement::fetchAll ([ int $fetch_style [, mixed$fetch_argument [, array $c tor_args= array() ]]] )
Dans ces méthodes, il est important de qualifier la façon dont on veut le retour des données grâce à fetch_style qui contrôle comment la prochaine ligne sera retournée à l'appelant.
Tableau de l'attribut fetch_style (Il existe d'autres attributs cf doc) :
PDO::FETCH_ASSOC | retourne un tableau indexé par le nom de la colonne comme retourné dans le jeu de résultats |
PDO::FETCH_BOTH | (défaut): retourne un tableau indexé par les noms de colonnes et aussi par les numéros de colonnes, commençant à l'index 0, comme retournés dans le jeu de résultats |
PDO::FETCH_OBJ: | retourne un objet anonyme avec les noms de propriétés qui correspondent aux noms des colonnes retournés dans le jeu de résultats |
Script : | Sortie : |
L’usage de fetchAll est souvent préféré à fecth, si dans la plupart des cas cela ne pose pas de problème cela peut avoir des incidences sur une requête ayant une lourde volumétrie car les tableaux en PHP ont des limites (notamment liées à la mémoire disponible).
Ex : résultat
100 000 d’enreg pour 10 ko=> 1000 000 Ko =>900Mo on ne peut pas utiliser un tableau
Dans le point 6.3 du document, j’indique que pour gérer la vue de la partie MVC, il existe deux méthodologies dont l’une est le Template de présentation.
Le développeur pourrait s’affranchir de la partie représentation, il pourrait développer la partie Modèle, passer le résultat soit au contrôleur soit à la vue sans savoir comment les données vont être affichées (web, PDF, XML …)
Le principe d’un système de Template est dans la séparation entre le contenu de l’information et la forme de sa représentation.
Avantage | Inconvénient | |
Template de présentation | Clarté dans le développement Facilité de développement à plusieurs (dev, graphiste) Productivité de développement. | Apprentissage du système de Template. Si pas de gestionnaire de cache, solution peu ralentir la création des pages web. |
9.2Exemple « fait maison » :
On veut créer une page web affichant le résultat d’une requête nous retournant qu’un enregistrement.
Fichier Template : Ce fichier comporte la page HTML avec des balises que l’on devra remplacer par les données provenant du résultat d’un script PHP. On voit bien ici, que l’on peut donner cette page à créer à un webdesigner. Il n’y a pas de programmation. |
On utilisera la requête du script de la page 28.
$req= "select * from user limit 0,1";
Le but est d'analyser le fichier de Template et remplacer les balises par les données en provenance du script de données.
On peut utiliser plusieurs méthodes pour arriver à ce but :
? Créer des tableaux : array(valeur_chercher) , array(valeur_remplacement) et matcher ? On peut utiliser des gestionnaires de chaines.
? On peut utiliser le remplacement via des fonctions d'expressions régulières
?
Pour l'exemple, on va utiliser les fonctions d'expressions régulières.
? | On n'utilise pas ce système avec un site à forte volumétrie. |
9.2.4Sortie HTML.
Au final :
Smarty est un gestionnaire de Template professionnel.
Quelques caractéristiques de Smarty :
? Il est efficace, le parser PHP s'occupe du sale travail.
? Pas d'analyse de Template coûteuse, une seule compilation.
? Il sait recompiler uniquement les fichiers de Template qui ont été modifiés.
? Syntaxe des Templates configurable, vous pouvez utiliser {}, {{}}, <!--{}-->, etc. comme délimiteurs tag.
? Les instructions if/elseif/else/endif sont passées au parser PHP. ? Support de cache intégré.
Ce Template est OO.
Pour l'utiliser, on inclut le moteur de Template "setup_smarty", on crée un objet et on utilise un pseudo langage pour les Templates.
Exemple de ce gestionnaire
Fichier de présentation
Script d'usage :
Lors d'un développement professionnel, on doit apporter un soin particulier à la gestion d'erreurs.
Une erreur est tout comportement inattendu par rapport à ce que le développeur voulait avoir.
Attention, on ne parle pas ici d'erreurs de conception.
On peut faire la distinction entre les erreurs lors du développement et les erreurs lors de la production de l'application.
Une erreur peut provenir :
? Erreur de syntaxe.
? Erreur de comportement.
? Erreur de parcours.
? Erreur du serveur ...
L'idée importante est de pouvoir repérer l'erreur, l'intercepter et/ou l'enregistrer. On veut un moyen pour connaitre l'erreur afin d'y remédier (ce n'est pas toujours évident).
Le moteur de PHP sait gérer des erreurs mais encore faut-il qu'il soit bien paramétré.
? Dans le fichier , on a une directive indiquant le niveau de remontée des erreurs par PHP.
Tableau niveaux d'erreurs
E_ALL | Toutes les erreurs et les warnings (E_ALL n'inclut pas tous les niveaux d'alerte) |
E_PARSE | Erreur de syntaxe |
E_ERROR | Erreur critique |
E_STRICT | Suggestions de PHP pour assurer une meilleure interopérabilité et compatibilité du code. |
E_DEPRECATED | Notice pour les éléments dépréciés dans le futur |
Il existe plusieurs niveaux d'erreurs (+10) avec des combinaisons entre eux. Les combinaisons sont écrites simplement :
error_reporting= E_ALL & ~E_PARSE [on reporte les erreurs E_ALL et pas celles remontées par E_PARSE ] error_reporting= E_ALL | E_STRICT [on reporte les erreurs remontées par E_ALL ou par E_STRICT ]
Si vous ne pouvez pas modifier le , vous pouvez utilisez en début de script la fonction :
error_reporting( E_ERROR | E_WARNING | E_PARSE);
? La directive d'affichage
La directive display_errors (On/Off) permet d'afficher ou pas les erreurs.
? La directive de log
La directive log_errors (On/Off) permet d'indiquer si on peut logger les erreurs. La directive error_log = "" indique où.
Logger les erreurs pour pouvoir les analyser et très important notamment lorsqu'une application est en production car on ne peut pas afficher les erreurs PHP aux utilisateurs.
? Utiliser @ devant une fonction pour qu'elle n'affiche pas d'erreur ou warning à condition que vous gériez l'erreur.
? Tester les retours des fonctions. Vous pouvez utilisez If/Else mais rend le code illisible.
? Utiliser la méthode 'OR'. Intéressant pour substituer les If/Else
? Déclencher une erreur avec trigger_error(); Très Propre mais apprentissage.
Ex de script :
La fonction trigger_error () :
bool trigger_error ( string $error_msg [, int $error_type = E_USER_NOTICE ] )
Les erreurs que l'on peut indiquer sont de 3 types :
E_USER_ERROR | = E_ERROR – Le script s'arrête |
E_USER_WARNING | =E_WARNING – Le script continue |
E_USER_NOTICE | =E_NOTICE – Le script continue |
? | L'utilisation de la fonction die ou exit() n'est pas un système de gestion d'erreur. | |
Les assertions sont des mécanismes pour tester la logique des données.
Ex : le développeur veut s'assurer qu'un nombre d'adhérents ne peut être négatif.
Attention : Les assertions ne doivent pas être utilisées pour gérer la logique de l'application.
La logique applicative est faite par des structures de contrôle If/Else/Elseif
En règle générale, les assertions sont utilisées pendant le développement et on doit pouvoir supprimer toutes les assertions lors de la mise en production de l'application.
Pour utiliser les assertions, il faut les activer :
On peut aussi les activer dans via la directive assert.active.
Utilisation des assertions :
Ex : On a une application qui doit gérer des prix. On récupère les prix via une requête, un calcul, ou dans un fichier par exemple. On sait que les prix des articles ne peuvent pas être <= 0. On va utiliser une assertion pour vérifier cela lors du développement.
On peut déduire que la donnée de prix récupérée n'est pas bonne, problème de requête, du calcul, de lecture du fichier...
L'assertion est un moyen rapide et simple de tester des informations.
Astuce :
? On peut dans mettre un commentaire dans le message d'assert(), ce qui permet de donner des indications lors du développement.
? On peut aussi créer une fonction permettant de gérer l'assertion avec assert_options(ASSERT_CALLBACK,'nom_fct_gestion_assertion')
On a vu plus haut l'usage de la levée d'exceptions lors d'une connexion à la base de données, ce mécanisme est très utile, pour le développeur car c'est lui qui détermine les problèmes qu'il veut remonter.
Les Exceptions permettent la gestion logique de l'application.
Comme en JAVA, la structure de gestion des exceptions est ?
Quand vous développez, pensez à lever (throw) et à attraper (catch) les exceptions, autrement dit c'est au développeur de savoir ce qu'il estime être une Exception.
PHP a par défaut 2 classes pour les exceptions :
? Classe Exception
? Classe ErrorException extends Exception
Avec ces classes ont a des méthodes pour travailler sur l'exception levée :
? getMessage() ? Récupère le message de l'exception
? getCode () ? Récupère le code de l'exception
? getFile() ? Récupère le fichier dans lequel l'exception est survenue
? getLine() ? Récupère la ligne dans laquelle l'exception est survenue
A Savoir :
? Le moteur PHP ne lève pas d'exception pour ses erreurs.
Ainsi, si vous faites une erreur de syntaxe E_PARSE n'envoit pas d'exception mais une erreur classique, c'est le cas pour tout les types d'erreurs PHP.
Ex : On imagine une application de calcul de prix TTC à partir du HT. On doit avoir un prix supérieur à 0 au niveau du prix HT sinon l'application n'a pas d'usage.
Script test_exception : | Affichage : Ce qui est important c'est l'usage de throw qui lève réellement l'exception. On peut utiliser la fonction : error_log ( string $message [, int $message_type = 0 [, string $destination [, string $extra_headers ]]] ) pour logger l'erreur ce qui est vivement conseillé. |
On peut créer sa propre classe d'exception en dérivant d'une classe exception.
Cela peut être utile notamment si vous développez des applications qui travaillent avec des ressources spécifiques (URL, Fichier, Base de données…)
Création d'une classe d'exception pour des ressources URL :
Pour une application web, le développeur est en face d'au moins 4 problématiques :
? Disponibilité de l'application –Le développeur doit s'assurer de la montée en charge.
? Intégrité des données – Le développeur est le garant des données.
? Intégrité du site – Le développeur doit s'assurer du détournement de l'application.
? Sécurité des données – Le développeur doit veiller à la non divulgation des données.
La sécurité est une préoccupation du développeur mais ne doit pas être une obsession.
11.2Tout le monde ment !
11.2.1Ne fait pas confiance au utilisateur.
Vérifier que la donnée est de la forme que vous attendez.
Pour la vérification, les expressions régulières et la fonction preg_match() sont redoutables.
Exemple :
Dans un formulaire, on demande le nom d'une personne.
On peut veut vérifier que le nom soit forcement entre 3 et 10 caractères alphabétiques majuscule ou minuscule.
Expression régulière : /^[a-z]{3,10}$/i
Informations sur les expressions régulières :
La fonction preg_match($_REGEX,$_DONNEE) renvoit 0 si le REGEX n'a pas été trouvé ou 1, on peut donc l'utiliser pour valider des données.
L'injection SQL est un moyen de détourner l'utilisation des requêtes de l'application.
Pour faire de l'injection SQL, il faut connaître un minimum le langage SQL et PHP.
Ex : Dans de nombreuses applications, l'utilisateur doit s'authentifier pour accéder à son compte. Une fois les données saisies, on lance une requête pour vérifier que la personne à un compte et qu'il est valide.
Page |
Page On récupère le login et le password et on construit une requête SQL que l'on va ensuite passer à notre base de données. |
Sortie SQL et résultat :
Login =fred et le password jkjklj
C'est Normal. Mais imaginons que je suis mal intentionné, et que je veux passer.
Login =theronf' –
Password ="vide"
Pourquoi, le système m'authentifie ?
Mon injection SQL a fonctionnée.
En SQL -- indique un commentaire, du coup la requête pour le système a été :
La requête écrite par le développeur n'a même pas été joué.
Comment se prévenir de ce type de problème : Tout le monde ment ! Donc vérifier les données. (11.2.1)
AvecPDO, vous pouvez créer des requetés préparées et utiliser la fonction PDO quote() pour gérer les problèmes de SQL.
Sinon utiliser une fonction spécifique à votre base de données :
? pour MySql : mysql_real_escape_string()],
? Pour PostGres : pg_escape_string
Ou utiliser addslashes(). ? Cette fonction n'est pas efficace sur tous les problèmes d'injection SQL
Avec PDO :
A Savoir :
Il existe dans , une variable magic_quotes_gpc qui fixe le mode magic_quotes pour les opérations GPC (Get/Post/Cookie). Lorsque magic_quotes est activé, tous les caractères ' (guillemets simples), " (guillemets doubles), \ (antislash) et NUL sont échappés avec un antislash. Avertissement : Cette fonctionnalité est OBSOLETE depuis PHP 5.3.0.
11.2.3 Session – Cookies et sécurité.
Le protocole HTTP est dit "stateless", ou autrement dit sans état. Pour un serveur, chaque requête qu'il reçoit est indépendante de la précédente par conséquent, il nous faut un mécanisme pour conserver les données de l'utilisateur, pour ce faire on peut utiliser les sessions et/ou les cookies.
Cookies :
Un cookie est généré et envoyée par un serveur HTTP à un client http qui le conserve (soit dans sa mémoire, soit dans un fichier texte), et ce dernier le retourne lors de chaque interrogation du même serveur HTTP.
Générer un cookie :
Le cookie doit etre la première chose créée dans une page php.
Lire un cookie :
Session :
La session est un mécanisme qui permet à PHP de garder "en mémoire" du côté du serveur un nombre illimité de valeurs entre plusieurs requêtes d'un même utilisateur. Une session est identifiée par un Id unique.
Créer une session :
Dans chaque page de l'application où on doit utiliser les sessions, il faut appeler cette fonction qui initialise la session. |
Affecter une valeur à la session. |
Du bon usage de la session et du cookie :
? Ne pas utiliser les cookies pour l'authentification (mot de passe). Fichier texte
? Stocker dans le cookie des informations non essentielles à l'usage du site. Le cookie peut être supprimé. ( ex : panier d'articles d'un site marchand)
? Lors de l'authentification dans la session, noter une information telle que l'adresse IP rend le vol de sessions plus compliqué, à condition de vérifier l'adresse IP dans le script.
? Pour rendre le vol de session, plus compliqué encore lier des données de la session avec des données du cookie et vérifier les deux données à chaque script.
? Utiliser des fonctions de cryptage pour des données sensibles. [md5(), mcrypt()]
Dans une application, les développeurs négligent souvent l'analyse des logs de production, c'est une erreur.
Dans le fichier , on peut indiquer où sont les logs mais si on ne les analyse pas régulièrement, on se prive d'informations importantes, mais il faut aussi analyser les logs du serveur web aussi qui donne de bonnes informations.
Log d'accès Apache (Log automatique):
Log d'erreur Apache (Log automatique):
Log d'Erreur PHP (Log créé cf. 10.3.2) :