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 (362 lines) | stat: -rw-r--r-- 15,521 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
357
358
359
360
361
362
<sect1 id="zend.controller.exceptions">
    <title>Wyjątki MVC</title>

    <sect2 id="zend.controller.exceptions.introduction">
        <title>Wprowadzenie</title>

        <para>
            Komponenty MVC w Zend Framework używają kontrolera frontowego, co
            oznacza, że wszystkie żądania do danej strony przechodzą przez
            pojedynczy punkt. W rezultacie wszystkie wyjątki ostatecznie
            zbierane są w kontrolerze frontowym, pozwalając programiście na
            obsłużenie ich w jednym miejscu.
        </para>

        <para>
            Jakkolwiek, wiadomości o wyjątkach oraz informacje o backtrace
            często zawierają wrażliwe informacje o systemie, jak np. zapytania
            SQL, informacje o lokacjach plików i wiele innych. Aby pomóc ci
            chronić swój serwis, domyślnie <code>Zend_Controller_Front</code>
            łapie wszystkie wyjątki i rejestruje je w obiekcie odpowiedzi; z
            kolei, obiekt odpowiedzi domyślnie nie wyświetla wiadomości o
            wyjątkach.
        </para>
    </sect2>

    <sect2 id="zend.controller.exceptions.handling">
        <title>W jaki sposób możesz obsługiwać wyjątki?</title>

        <para>
            Obecnie w komponentach MVC wbudowanych jest kilka mechanizmów
            pozwalających na obsługę wyjątków
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    Domyślnie rejestrowana i aktywna jest <link
                        linkend="zend.controller.plugins.standard.errorhandler">wtyczka
                    obsługi błędów</link>. Ta wtyczka została stworzona aby
                    obsługiwać:
                </para>

                <itemizedlist>
                    <listitem><para>Błędy spowodowane brakującym kontrolerem lub akcją</para></listitem>

                    <listitem><para>Błędy występujące wewnątrz akcji kontrolerów</para></listitem>
                </itemizedlist>

                <para>
                    Wtyczka działa w oparciu o metodę <code>postDispatch()</code>,
                    i sprawdza czy obiekt uruchamiający, kontroler akcji, lub
                    inny obiekt wyrzucił wyjątek. Jeśli tak, przekazuje ona
                    żądanie do kontrolera obsługi błędu.
                </para>

                <para>
                    Ta wtyczka obsłuży większość sytuacji, w których został
                    wyrzucony wyjątek, a także poprawnie obsłuży brakujące
                    kontrolery oraz akcje.
                </para>
            </listitem>

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

                <para>
                    Przekazująć logiczną wartość true do tej metody, możesz
                    nakazać kontrolerowi frontowemu aby zamiast składować
                    wyjątki w obiekcie odpowiedzi, wyrzucił je, żebyś mógł
                    obsłużyć je samodzielnie. Na przykład:
                </para>

                <programlisting role="php"><![CDATA[
$front->throwExceptions(true);
try {
    $front->dispatch();
} catch (Exception $e) {
    // sam obsłuż wyjątki
}
]]>
                </programlisting>

                <para>
                    Ta metoda jest najprawdopodobniej najłatwiejszym sposobem
                    dodania własnej obsługi wyjątków do twojej aplikacji
                    używającej kontrolera frontowego.
                </para>
            </listitem>

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

                <para>
                    Przekazując logiczną wartość true do tej metody, możesz
                    nakazać obiektowi odpowiedzi aby renderował on wyjątki gdy
                    sam będzie renderowany. W takim scenariuszu, każdy wyjątek
                    wyrzucony w twojej aplikacji będzie wyświetlony. To jest
                    jedynie rekomendowane dla nieprodukcyjnych środowisk.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>Zend_Controller_Front::returnResponse()</code> oraz
                    <code>Zend_Controller_Response_Abstract::isException()</code>
                </para>

                <para>
                    Przekazanie wartości logicznej true do metody
                    <code>Zend_Controller_Front::returnResponse()</code>,
                    spowoduje, że obiekt
                    <code>Zend_Controller_Front::dispatch()</code> nie będzie
                    renderował odpowiedzi, a zamiast tego ją zwróci. Gdy już
                    masz odpowiedź, możesz sprawdzić czy są w niej wyjątki
                    używając metody <code>isException()</code>, a następnie
                    odebrać wyjątki używając metody <code>getException()</code>.
                    Na przykład:
                </para>

                <programlisting role="php"><![CDATA[
$front->returnResponse(true);
$response = $front->dispatch();
if ($response->isException()) {
    $exceptions = $response->getException();
    // obsługa wyjątków ...
} else {
    $response->sendHeaders();
    $response->outputBody();
}
]]>
                </programlisting>

                <para>
                    Główną zaletą, dzięki której ta metoda umożliwia więcej niż
                    <code>Zend_Controller_Front::throwExceptions()</code>, jest
                    to, że możesz warunkowo wyświetlać odpowiedź po obsłudze
                    wyjątków.
                </para>
            </listitem>
        </itemizedlist>
    </sect2>

    <sect2 id="zend.controller.exceptions.internal">
        <title>Wyjątki MVC które możesz napotkać</title>

        <para>
            Różne komponenty MVC -- obiekt żądania, router, obiekt uruchamiający,
            kontrolery akcji, oraz obiekt odpowiedzi -- każdy może z różnych
            przyczyn wyrzucać wyjątki. Niektóre wyjątki mogą być warunkowo
            nadpisane, a inne są używane aby wskazać programiście potrzebę
            poprawienia aplikacji.
        </para>

        <para>Kilka przykładów:</para>

        <itemizedlist>
            <listitem>
                <para>
                    <code>Zend_Controller_Dispatcher::dispatch()</code>
                    domyślnie wyrzuci wyjątek jeśli zażądano nieprawidłowego
                    kontrolera. Są dwa zalecane sposoby na obsłużenie tego:
                </para>

                <itemizedlist>
                    <listitem>
                        <para>Ustawienie parametru <code>useDefaultControllerAlways</code>.</para>

                        <para>
                            W twoim kontrolerze frontowym, lub w obiekcie
                            uruchamiającym, dodaj poniższą dyrektywę:
                        </para>

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

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

                        <para>
                            Gdy ta flaga jest ustawiona, obiekt uruchamiający,
                            użyje domyślnego kontrolera oraz akcji zamiast
                            wyrzucania wyjątku. Minusem użycia tej metody jest
                            to, że jakikolwiek błąd literowy w adresie
                            dostępowym do twojej strony spowoduje wyświetlenie
                            strony głównej, co może źle wpłynąć na optymalizację
                            serwisu dla wyszukiwarek internetowych.
                        </para>
                    </listitem>

                    <listitem>
                        <para>
                            Wyjątek wyrzucany przez metodę <code>dispatch()</code>
                            jest wyjątkiem <code>Zend_Controller_Dispatcher_Exception</code>
                            zawierającym tekst 'Invalid controller specified'.
                            Użyj jednej z metod opisanych w <link
                            linkend="zend.controller.exceptions.handling">poprzedniej
                            sekcji</link> aby złapać wyjątek, a następnie
                            przekierować do strony błędu lub do strony głownej.
                        </para>
                    </listitem>
                </itemizedlist>
            </listitem>

            <listitem>
                <para>
                    Metoda <code>Zend_Controller_Action::__call()</code> wyrzuci
                    wyjątek <code>Zend_Controller_Action_Exception</code>
                    jeśli nie może uruchomić nieistniejącej metody akcji.
                    Najczęściej będziesz chciał użyć jakiejś domyślnej akcji
                    w kontrolerze w tego typu sprawach. Przykładowe metody
                    za pomocą których możesz to osiśgnąć:
                </para>

                <itemizedlist>
                    <listitem>
                        <para>
                            Rozszerzenie klasy <code>Zend_Controller_Action</code>
                            i nadpisanie metody <code>__call()</code>. Na przykład:
                        </para>

                        <programlisting role="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('Invalid method');
    }
}
]]>
                        </programlisting>
                        <para>
                            Powyższa metoda przechwytuje wszystkie wywołane
                            niezdefiniowane akcje i przekierowuje żądanie do
                            domyślnej akcji w kontrolerze.
                        </para>
                    </listitem>

                    <listitem>
                        <para>
                            Rozszerzenie klasy <code>Zend_Controller_Dispatcher</code> o
                            nadpisanie metody <code>getAction()</code>, która
                            sprawdza czy akcja istnieje. Na przykład:
                        </para>

                        <programlisting role="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>
                            Powyższy kod sprawdza czy zażądana akcja istnieje w
                            klasie kontrolera; jeśli nie, resetuje akcję do
                            akcji domyślnej.
                        </para>

                        <para>
                            Ta metoda jest wygodna ponieważ możesz w niewidoczny
                            sposób zmienić akcję przed ostatecznym uruchomieniem.
                            Jednak to także oznacza, że jakikolwiek błąd literowy
                            w adresie URL może wciąż uruchomić żądanie poprawnie,
                            co nie jest zbyt dobre dla optymalizacji dla
                            wyszukiwarek internetowych.
                        </para>
                    </listitem>

                    <listitem>
                        <para>
                            Użycie metody <code>Zend_Controller_Action::preDispatch()</code>
                            lub <code>Zend_Controller_Plugin_Abstract::preDispatch()</code>
                            do zidentyfikowania nieprawidłowych akcji.
                        </para>

                        <para>
                            Rozszerzając klasę <code>Zend_Controller_Action</code> i
                            modyfikując metodę <code>preDispatch()</code>, możesz
                            zmodyfikować wszystkie twoje kontrolery w taki
                            sposób, aby przenosiły one żądanie do innej akcji
                            lub przekierowywały zamiast uruchamiać akcję.
                            Kod wyglądałby podobnie kod nadpisujący metodę
                            <code>__call()</code>, który został przedstawiony wyżej.
                        </para>

                        <para>
                            Alternatywnie, możesz sprawdzać te informacje we
                            wtyczce globalnej. Zaletą tego rozwiązania jest to,
                            że kontroler akcji staje się niezależny; jeśli twoja
                            aplikacja składa się z różnorodnych kontrolerów
                            akcji i nie wszystkie dziedziczą z tej samej klasy,
                            ta metoda może dodać konsekwencji w obsłudze różnych
                            klas.
                        </para>

                        <para>
                            Przykład:
                        </para>

                        <programlisting role="php"><![CDATA[
class My_Controller_PreDispatchPlugin extends Zend_Controller_Plugin_Abstract
{
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $dispatcher = Zend_Controller_Front::getInstance()->getDispatcher();
        $controller = $dispatcher->getController($request);
        if (!$controller) {
            $controller = $dispatcher->getDefaultControllerName($request);
        }
        $action     = $dispatcher->getAction($request);

        if (!method_exists($controller, $action)) {
            $defaultAction = $dispatcher->getDefaultAction();
            $controllerName = $request->getControllerName();
            $response = Zend_Controller_Front::getInstance()->getResponse();
            $response->setRedirect('/' . $controllerName . '/' . $defaultAction);
            $response->sendHeaders();
            exit;
        }
    }
}
]]>
                        </programlisting>

                        <para>
                            W tym przykładzie sprawdzamy czy zażądana akcja
                            jest dostępna w kontrolerze. Jeśli nie,
                            przekierujemy żądanie do domyślnej akcji w
                            kontrolerze, i kończymy wykonywanie skryptu.
                        </para>
                    </listitem>
                </itemizedlist>
            </listitem>
        </itemizedlist>
    </sect2>
</sect1>