File: Zend_Controller-Exceptions.xml

package info (click to toggle)
zendframework 1.12.9%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 133,584 kB
  • sloc: xml: 1,311,829; php: 570,173; sh: 170; makefile: 125; sql: 121
file content (356 lines) | stat: -rw-r--r-- 16,301 bytes parent folder | download | duplicates (2)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: no -->
<sect1 id="zend.controller.exceptions">
    <title>MVC Ausnahmen</title>

    <sect2 id="zend.controller.exceptions.introduction">
        <title>Einführung</title>

        <para>
            Die <acronym>MVC</acronym> Komponenten im Zend Framework verwenden einen Front
            Controller, was bedeutet das alle Anfragen zu einer bestimmten Site über einen
            einzelnen Eintrittspunkt laufen. Als Ergebnis treten alle Ausnahmen eventuell am Front
            Controllerauf, was es Entwicklern erlaubt diese an einem einzelnen Ort zu behandeln.
        </para>

        <para>
            Trotzdem enthalten Ausnahmemeldungen und Backtrace Informationen oft sensitive
            Systeminformationen, wie <acronym>SQL</acronym> Anweisungen, Dateiorte, und andere. Um
            zu helfen die eigene Site zu schützen, werden standardmäßig alle Ausnahmen von
            <classname>Zend_Controller_Front</classname> gefangen und im Antwortobjekt registriert;
            zusätzlich zeigt das Antwortobjekt die Ausnahmemeldungen standardmäßig nicht an.
        </para>
    </sect2>

    <sect2 id="zend.controller.exceptions.handling">
        <title>Behandeln von Ausnahmen</title>

        <para>
            Verschiedene Mechanismen sind bereits in die <acronym>MVC</acronym> Komponenten
            eingebaut um die Behandlung von Ausnahmen zu erlauben.
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    Standardmäßig ist das
                    <link linkend="zend.controller.plugins.standard.errorhandler">Error Handler
                        Plugin</link> registriert und aktiv. Dieses Plugin wurde erstellt um
                    folgendes zu behandeln:
                </para>

                <itemizedlist>
                    <listitem><para>Fehler durch fehlende Controller oder Aktionen</para></listitem>
                    <listitem><para>Fehler die in Actioncontrollern auftreten</para></listitem>
                </itemizedlist>

                <para>
                    Es arbeitet als <methodname>postDispatch()</methodname> Plugin und prüft ob
                    eine Dispatcher, Actioncontroller oder andere Ausnahme aufgetreten ist. Wenn
                    das so ist, leitet es an den Error Handler Controller weiter.
                </para>

                <para>
                    Dieser Handler deckt die meisten Ausnahmesituationen ab, und behandelt fehlende
                    Controller und Aktionen taktvoll.
                </para>
            </listitem>

            <listitem>
                <para><methodname>Zend_Controller_Front::throwExceptions()</methodname></para>

                <para>
                    Durch die Übergabe eines boolschen <constant>TRUE</constant> Wertes an diese
                    Methode, kann dem Front Controller mitgeteilt werden das, statt der Ansammlung
                    der Ausnahmen im Antwortobjekt oder der Verwendung des Error Handler Plugin's,
                    man diese Ausnahmen selbst behandeln will. Als Beispiel:
                </para>

                <programlisting language="php"><![CDATA[
$front->throwExceptions(true);
try {
    $front->dispatch();
} catch (Exception $e) {
    // Ausnahmen selbst behandeln
}
]]></programlisting>

                <para>
                    Diese Methode ist möglicherweise der einfachste Weg um eigene
                    Ausnahmebehandlungen hinzuzufügen die den vollen Umfang der möglichen Ausnahmen
                    der Front Controller Anwendung behandeln.
                </para>
            </listitem>

            <listitem>
                <para>
                    <methodname>Zend_Controller_Response_Abstract::renderExceptions()</methodname>
                </para>

                <para>
                    Durch die Übergabe eines boolschen <constant>TRUE</constant> Wertes an diese
                    Methode kann dem Antwortobjekt mitgeteilt werden das es Ausnahmenachrichten und
                    Backtrace darstellen soll, wenn es selbst dargestellt wird. In diesem Szenario
                    wird jede Ausnahme die an der Anwendung auftritt angezeigt. Das wird nur in
                    nicht-produktiven Umgebungen vorgeschlagen.
                </para>
            </listitem>

            <listitem>
                <para>
                    <methodname>Zend_Controller_Front::returnResponse()</methodname> und
                    <methodname>Zend_Controller_Response_Abstract::isException()</methodname>.
                </para>

                <para>
                    Durch die Übergabe eines boolschen <constant>TRUE</constant> an
                    <methodname>Zend_Controller_Front::returnResponse()</methodname>, wird
                    <methodname>Zend_Controller_Front::dispatch()</methodname> die Antwort nicht
                    darstellen, aber diese stattdessen zurückgeben. Sobald man die antwort hat,
                    kann diese getestet werden um zu sehen ob irgendwelche Ausnahmen gefangen
                    wurden indem die <methodname>isException()</methodname> Methode verwendet, und
                    die Ausnahme über die <methodname>getException()</methodname> Methode empfangen
                    wird. Als Beispiel:
                </para>

                <programlisting language="php"><![CDATA[
$front->returnResponse(true);
$response = $front->dispatch();
if ($response->isException()) {
    $exceptions = $response->getException();
    // Ausnahme behandeln ...
} else {
    $response->sendHeaders();
    $response->outputBody();
}
]]></programlisting>

                <para>
                    Der primäre Vorteil welche diese Methode über
                    <methodname>Zend_Controller_Front::throwExceptions()</methodname> bietet ist,
                    das Sie es erlaubt die Antwort wahlweise darzustellen nachdem die Ausnahme
                    behandelt wurde. Das fängt jede Ausnahme in der Controllerkette, im Gegensatz
                    zum Error Handler Plugin.
                </para>
            </listitem>
        </itemizedlist>
    </sect2>

    <sect2 id="zend.controller.exceptions.internal">
        <title>MVC Ausnahme die auftreten können</title>

        <para>
            Die verschiedenen <acronym>MVC</acronym> Komponenten -- Anfragen, Router, Dispatcher,
            Actioncontroller, und Antwortobjekte -- können alle gelegentlich Ausnahmen werfen.
            Einige Ausnahmen können wahlweise überschrieben werden und andere werden Verwendet um
            dem Entwickler anzuzeigen das die eigene Struktur der Anwendung überdacht werden
            sollte.
        </para>

        <para>Einige Beispiele:</para>

        <itemizedlist>
            <listitem>
                <para>
                    <methodname>Zend_Controller_Dispatcher::dispatch()</methodname> wird
                    standardmäßig eine Ausnahme werfen wenn ein ungültiger Controller angefragt
                    wird. Es gibt zwei empfohlene Wege um damit umzugehen.
                </para>

                <itemizedlist>
                    <listitem>
                        <para>
                            Den <property>useDefaultControllerAlways</property> Parameter setzen.
                        </para>

                        <para>
                            Im eigenen Frontcontroller, oder dem eigenen Dispatcher, die folgende
                            Anweisung hinzufügen:
                        </para>

                        <programlisting language="php"><![CDATA[
$front->setParam('useDefaultControllerAlways', true);

// oder

$dispatcher->setParam('useDefaultControllerAlways', true);
]]></programlisting>

                        <para>
                            Wenn dieses Flag gesetzt ist, wird der Dispatcher den Standardcontroller
                            und die Standardaktion verwenden statt eine Ausnahme zu werfen. Der
                            Nachteil dieser Methode ist das jegliche Schreibfehler die ein Benutzer
                            macht wenn er auf die Site zugreift, trotzdem aufgelöst werden und die
                            Homepage angezeigt wird, was bei der Optimierung von Suchmaschienen
                            verherenden Schaden anrichten kann.
                        </para>
                    </listitem>

                    <listitem>
                        <para>
                            Die Ausnahme die von <methodname>dispatch()</methodname> geworfen wird,
                            ist eine <classname>Zend_Controller_Dispatcher_Exception</classname>
                            die den Text 'Invalid controller specified' enthält. Eine der Methoden
                            die in <link linkend="zend.controller.exceptions.handling">der
                                vorhergehenden Sektion</link> beschrieben wurden können verwendet
                            werden um die Ausnahme zu fangen und dann zu einer generellen
                            Fehlerseite oder der Homepage umzuleiten.
                        </para>
                    </listitem>
                </itemizedlist>
            </listitem>

            <listitem>
                <para>
                    <methodname>Zend_Controller_Action::__call()</methodname> wird eine
                    <classname>Zend_Controller_Action_Exception</classname> geworfen wenn eine nicht
                    existierende Aktion einer Methode nicht dargestellt werden kann. Normalerweise
                    wird es gewünscht sein in Fällen wie diesen eine Standardaktion im Controller zu
                    verwenden. Wege um das zu tun beinhalten:
                </para>

                <itemizedlist>
                    <listitem>
                        <para>
                            Eine Subklasse von <classname>Zend_Controller_Action</classname>
                            erstellen und die <methodname>__call()</methodname> Methode
                            überschreiben. Als Beispiel:
                        </para>

                        <programlisting language="php"><![CDATA[
class My_Controller_Action extends Zend_Controller_Action
{
    public function __call($method, $args)
    {
        if ('Action' == substr($method, -6)) {
            $controller = $this->getRequest()->getControllerName();
            $url = '/' . $controller . '/index';
            return $this->_redirect($url);
        }

        throw new Exception('Ungültige Methode');
    }
}
]]></programlisting>
                        <para>
                            Das obige Beispiel fängt jede nicht definierte Aktionsmethode ab die
                            aufgerufen wird und leitet Sie zur Standardaktion im Controller um.
                        </para>
                    </listitem>

                    <listitem>
                        <para>
                            Eine Subklasse von <classname>Zend_Controller_Dispatcher</classname>
                            erstellen und die <methodname>getAction()</methodname> Methode
                            überschreiben um zu prüfen ob die Aktion existiert. Als Beispiel:
                        </para>

                        <programlisting language="php"><![CDATA[
class My_Controller_Dispatcher extends Zend_Controller_Dispatcher
{
    public function getAction($request)
    {
        $action = $request->getActionName();
        if (empty($action)) {
            $action = $this->getDefaultAction();
            $request->setActionName($action);
            $action = $this->formatActionName($action);
        } else {
            $controller = $this->getController();
            $action     = $this->formatActionName($action);
            if (!method_exists($controller, $action)) {
                $action = $this->getDefaultAction();
                $request->setActionName($action);
                $action = $this->formatActionName($action);
            }
        }

        return $action;
    }
}
]]></programlisting>

                        <para>
                            Der obige Code prüft ob die angefragte Aktion in der Controllerklasse
                            existiert ; wenn nicht wird die Aktion auf die Standardaktion
                            zurückgesetzt.
                        </para>

                        <para>
                            Diese Methode ist nützlich, weil Sie die Aktion transparent ändert bevor
                            diese letztendlich dargestellt wird. Trotzdem bedeutet es auch, das
                            Schreibfehler in der <acronym>URL</acronym> trotzdem richtig dargestellt
                            werden, was für die Optimierung von Suchmaschinen nicht gut ist.
                        </para>
                    </listitem>

                    <listitem>
                        <para>
                            Verwenden von
                            <methodname>Zend_Controller_Action::preDispatch()</methodname> oder
                            <methodname>Zend_Controller_Plugin_Abstract::preDispatch()</methodname>
                            um eine ungültige Aktion zu identifizieren.
                        </para>

                        <para>
                            Durch das Erstellen einer Subklasse von
                            <classname>Zend_Controller_Action</classname> und dem modifizieren von
                            <methodname>preDispatch()</methodname>, können alle eigenen Controller
                            geändert werden damit Sie an andere Aktionen weiterleiten oder umleiten
                            bevor die Aktion letztendlich dargestellt wird. Der Code hierfür schaut
                            ähnlich wie der Code für das Überschreiben von
                            <methodname>__call()</methodname> aus, der oben schon angezeigt wurde.
                        </para>

                        <para>
                            Alternativ kann diese Information in einem globalen Plugin geprüft
                            werden. Das hat den Vorteil das es unabhängig von Actioncontroller ist;
                            wenn die eigene Anwendung aus einer Reihe von Actioncontrollern besteht,
                            und nicht alle von der gleichen Klasse abgeleitet sind, kann diese
                            Methode Kontinuität in der Handhabung der verschiedenen Klassen bringen.
                        </para>

                        <para>
                            Als Beispiel:
                        </para>

                        <programlisting language="php"><![CDATA[
class My_Controller_PreDispatchPlugin extends Zend_Controller_Plugin_Abstract
{
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $front      = Zend_Controller_Front::getInstance();
        $dispatcher = $front->getDispatcher();
        $class      = $dispatcher->getControllerClass($request);
        if (!$class) {
            $class = $dispatcher->getDefaultControllerClass($request);
        }

        $r      = new ReflectionClass($class);
        $action = $dispatcher->getActionMethod($request);

        if (!$r->hasMethod($action)) {
            $defaultAction  = $dispatcher->getDefaultAction();
            $controllerName = $request->getControllerName();
            $response       = $front->getResponse();
            $response->setRedirect('/' . $controllerName
                                  . '/' . $defaultAction);
            $response->sendHeaders();
            exit;
        }
    }
}
]]></programlisting>

                        <para>
                            In diesem Beispiel wird geprüft ob die angefragte Aktion im Controller
                            vorhanden ist. Wenn dem nicht so ist, wird auf die Standardaktion im
                            Controller umgeleitet und die Ausführung des Sktipts sofort beendet.
                        </para>
                    </listitem>
                </itemizedlist>
            </listitem>
        </itemizedlist>
    </sect2>
</sect1>