summaryrefslogtreecommitdiff
path: root/demos/blog-tutorial/protected/pages/Day5/fr/ErrorLogging.page
blob: 8e7c77e6adca262f6a9fbe1b9dc7329fee4588ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<com:TContent ID="Main">

<h1>Gestion et journalisation d'erreur</h1>

<p>
Si vous tentez de naviguez à l'URL <tt>http://hostname/blog/index.php?page=EditPost&id=100</tt>, vous verrez la page d'erreur suivante parce que le message avec l'ID 100 n'existe pas pour le moment. Nous voudrions personnaliser cette page d'erreur de manière à ce qu'elle garde la présentation générale du site. Nous voudrions aussi journaliser cette erreur pour étudier le comportement des utilisateurs. Dans cette section, nous allons mettre en place ces deux fonctionnalités.
</p>

<img src="<%~ output2.gif %>" class="output" />

<com:InfoBox>
Une des tâches importantes dans les applications Web est la <a href="http://www.pradosoft.com/demos/quickstart/?page=Advanced.Error">gestion des erreurs</a> ainsi que leurs <a href="http://www.pradosoft.com/demos/quickstart/?page=Advanced.Logging">journalisation</a>. Il y a deux types d'erreurs qui peuvent se produire dans une application PRADO : celles provenant des développeurs et celles des utilisateurs. Les premières doivent être résolues avant que l'application ne soit en production, tandis que les deuxièmes sont généralement un problème de prise en charge au niveau du design et doivent être gérées proprement (ie: journaliser cette erreur et indiquer à l'utilisateur que faire après). PRADO fournit un ensemble de fonctionnalités très utiles pour gérer et journaliser les erreurs.
</com:InfoBox>


<h2>Personnalisation de la gestion d'erreur</h2>

<p>
PRADO charge de manière implicite un module de gestion d'erreurs. Nous voulons personnaliser ce module pour qu'il affiche une page spécifique pour les erreurs causées par les utilisateurs. Nous modifions donc notre application comme ci-dessous :
</p>

<com:TTextHighlighter CssClass="source" Language="xml">
......
<modules>
    ......
    <module class="Application.BlogErrorHandler" />
    ......
</modules>
......
</com:TTextHighlighter>

<p>
La classe <tt>BlogErrorHandler</tt> comme spécifiée ci-dessus est un nouveau gestionnaire d'erreur que nous allons créer après. Il étend et remplace le module par défaut <tt>TErrorHandler</tt>.
</p>

<p>
Nous créons un fichier nommé <tt>protected/BlogErrorHandler.php</tt> avec le contenu suivant. La classe <tt>BlogErrorHandler</tt> surcharge deux méthodes de <tt>TErrorHandler</tt> :
</p>
<ul>
  <li><tt>getErrorTemplate()</tt> - cette méthode renvoie le gabarit utilisé pour afficher un message d'erreur utilisateur.</li>
  <li><tt>handleExternalError()</tt> - cette méthode est appelée lorsqu'une erreur utilisateur se produit et elle affiche l'erreur.</li>
</ul>
<com:TTextHighlighter CssClass="source" Language="php">
Prado::using('System.Exceptions.TErrorHandler');
Prado::using('Application.BlogException');

class BlogErrorHandler extends TErrorHandler
{
	/**
	 * Renvoi le fichier gabarit utilisé pour afficher l'erreur.
	 * Cette méthode surcharge la méthode originale.
	 */
	protected function getErrorTemplate($statusCode,$exception)
	{
		// on utilise notre propre gabarit pour BlogException
		if($exception instanceof BlogException)
		{
			// récupère le chemin du fichier de gabarit : protected/error.html
			$templateFile=Prado::getPathOfNamespace('Application.error','.html');
			return file_get_contents($templateFile);
		}
		else // sinon on utilise le gabarit par défaut.
			return parent::getErrorTemplate($statusCode,$exception);
	}

	/**
	 * Gère les erreurs causées par les utilisateurs.
	 * Cette méthode surcharge la méthode originale.
	 * Elle est appelée lorsqu'une exception utilisateur est générée.
	 */
	protected function handleExternalError($statusCode,$exception)
	{
		// Journaliser l'erreur (seulement pour BlogException)
		if($exception instanceof BlogException)
			Prado::log($exception->getErrorMessage(),TLogger::ERROR,'BlogApplication');
		// appelle l'implémentation de la classe parente
		parent::handleExternalError($statusCode,$exception);
	}
}
</com:TTextHighlighter>

<p>
Dans le code précédent, nous spécifions que lorsqu'une exception de type <tt>BlogException</tt> est générée, nous utilisons le gabarit <tt>protected/error.html</tt> pour afficher l'erreur. Par ailleurs, nous devons créer la classe <tt>BlogException</tt> et remplacer toutes les occurrences de <tt>THttpException</tt> dans notre code (par exemple dans les pages <a href="?page=Day3.CreateEditUser">EditUser</a> et <a href="?page=Day4.CreateReadPost">ReadPost</a>). Nous devons aussi créer le gabarit <tt>protected/error.html</tt>. La classe <tt>BlogException</tt> hérite de <tt>THttpException</tt> et est vide. Le fichier de classe est enregistré sous <tt>protected/BlogException.php</tt>.
</p>

<com:TTextHighlighter CssClass="source" Language="php">
class BlogException extends THttpException
{
}
</com:TTextHighlighter>

<p>
Ci-dessous le contenu du gabarit <tt>protected/error.html</tt>. Remarquez que ce gabarit n'est pas un gabarit PRADO, ceci parce qu'il ne reconnait qu'un nombre limité de mots clés, par exemple <tt>%%ErrorMessage%%</tt>, <tt>%%ServerAdmin%%</tt>.
</p>

<com:TTextHighlighter CssClass="source" Language="xml">
<html>
<head>
<title>%%ErrorMessage%%</title>
</head>
<body>
<div id="page">
<div id="header">
<h1>Mon Blog</h1>
</div>
<div id="main">
<p style="color:red">%%ErrorMessage%%</p>
<p>
Une erreur est apparue lors du traitement de votre demande.
</p>
<p>
Si vous pensez que c'est une erreur de notre serveur, veuillez contacter <a href="mailto:%%ServerAdmin%%">webmaster</a>.
</p>
</div>
</body>
</html>
</com:TTextHighlighter>


<h2>Journalisation des erreurs</h2>

<p>
Dans la méthode <tt>handleExternalError()</tt> de <tt>BlogErrorHandler</tt>, nous appelons <tt>Prado::log()</tt> pour journaliser l'erreur si elle est de type <tt>BlogException</tt>. L'erreur est stockée en mémoire. Pour enregistrer le journal d'erreur sur un support non volatil, tel que le disque dur ou une base de données, nous devons indiquer à PRADO comment procéder. Ceci est fait par la configuration d'application suivante :
</p>

<com:TTextHighlighter CssClass="source" Language="xml">
......
<modules>
    ......
    <module id="log" class="System.Util.TLogRouter">
        <route class="TFileLogRoute" Categories="BlogApplication" />
    </module>
    ......
</modules>
......
</com:TTextHighlighter>

<p>
Dans le code ci-dessus, nous ajoutons une "route" pour enregistrer le journal d'erreur dans un fichier. Nous spécifions aussi le filtre de catégorie <tt>BlogApplication</tt>, de manière à ce que seules les erreurs de type <tt>BlogApplication</tt> soient sauvegardées. Cette possibilité permet de réduire la taille du journal et d'en améliorer la lisibilité.
</p>

<h2>Test</h2>
<p>
Pour voir comme notre blog se comporte suite à une demande invalide, nous naviguons à l'URL <tt>http://hostname/blog/index.php?page=posts.ReadPost&id=100</tt>. Nous devrions voir la page suivante qui est différente de celle vue précédemment.
</p>

<img src="<%~ output3.gif %>" class="output" />

<p>
Si nous regardons dans le dossier <tt>protected/runtime</tt>, nous devrions y trouver un fichier nommé <tt>prado.log</tt>. C'est le journal d'erreur que nous venons juste de paramétrer. Le fichier pourrait contenir quelque chose comme :
</p>

<com:TTextHighlighter CssClass="source" Language="text">
Jun 28 22:15:27 [Error] [BlogApplication] Unable to find the specified post.
Jun 29 08:42:57 [Error] [BlogApplication] Unable to find the specified post.
</com:TTextHighlighter>

</com:TContent>