Spis treści
Zend_Controller
dostarcza system umożliwiający budowę witryny
opartej na wzorcu MVC (Model-View-Controller - Model-Widok-Kontroler).
System Zend_Controller
został zaprojektowany aby być lekkim,
modułowym i rozszerzalnym. Projekt jest minimalistyczny w celu zapewnienia
elastyczności i wolności użytkownikom, jednak zapewniając wystarczającą
strukturę powoduje, że systemy zbudowane w oparciu o
Zend_Controller
będą napisane w podobnych konwencjach.
System Zend_Controller
został zaimplementowany jako kilka
komponentów. Nie jest wymagane posiadanie dokładnej wiedzy na temat
działania wszystkich tych komponentów, jednak znajomość tego procesu
może być pomocna.
Zend_Controller_Front
instrumentuje całą
przestrzeń systemu Zend_Controller
. Jest
interpretacją wzorca projektowego FrontController.
Obiekt Zend_Controller_Front
przetwarza
wszystkie żądania otrzymywane przez serwer i jest
ostatecznie odpowiedzialny za przekazywanie żądań do
odpowiednich kontrolerów
(Zend_Controller_Action
).
Zend_Controller_Request_Abstract
reprezentuje środowisko żądania i zapewnia metody do
ustawienia i odebrania nazw kontrolera i akcji oraz
parametrów żądania. Dodatkowo przechowuje informacje o
tym, czy akcja z tego żądania została uruchomiona przez
Zend_Controller_Dispatcher
czy nie.
Rozszerzenia do abstrakcyjnego obiektu żądania mogą być
użyte aby obudować całe środowisko żądania, pozwalając
routerom na wyciągnięcie informacji ze środowiska
żądania w celu ustawienia nazwy kontrolera i akcji.
Domyślnie używany jest obiekt,
Zend_Controller_Request_Http
, ktory zapewnia
dostęp do całości środowiska żądania HTTP.
Interfejs Zend_Controller_Router_Interface
jest używany do definiowania tras. Routing jest procesem
badania środowiska żądania w celu określenia który
kontroler i która akcja tego kontrolera powinny odebrać
żądanie. Nazwa tego kontrolera, akcji oraz opcjonalnych
parametrów są ustawione w obiekcie żądania a następnie
przetwarzane przez
Zend_Controller_Dispatcher_Standard
.
Routing przeprowadzany jest tylko raz: wtedy kiedy
żądanie jest po raz pierwszy odebrane, a przed
uruchomieniem pierwszego kontrolera.
Domyślnym routerem jest
Zend_Controller_Router_Rewrite
.
Domyśłny router, Zend_Controller_Router_Rewrite
,
pobiera adres URI, który jest określony w obiekcie
Zend_Controller_Request_Http
i wyciąga z
niego informacje o kontrolerze, akcji oraz parametrach
w oparciu o informacje z adresu url. Na przykład, adres
URL http://localhost/foo/bar/key/value
może być zdekodowany jako kontroler foo
,
akcja bar
, i parametr key
o wartości value
.
Zend_Controller_Router_Rewrite
może być
także użyty do dopasowania bezwzlędnych ścieżek; zobacz
dokumentację rewrite routera aby dowiedzieć się
więcej.
Zend_Controller_Dispatcher_Interface
jest
używany do definiowania klas uruchamiających.
Uruchamianie jest procesem pobierania kontrolera i akcji
z obiektu żądania, określania na ich podstawie pliku
kontrolera, klasy oraz metody akcji w klasie kontrolera.
Jeśli kontroler lub akcja nie istnieje, obsługuje on
określanie domyślnych kontrolerów i akcji do
uruchomienia.
Aktualny proces uruchamiania składa się z tworzenia instancji klasy kontrolera i wywoływania metody akcji tej klasy. W przeciwieństwie do routingu, który występuje raz, uruchamianie występuje w pętli. Jeśli status uruchomienia w obiekcie żądania zostanie w którymkolwiek momencie zresetowany, pętla zostanie powtórzona, wywołując akcję która jest obecnie ustawiona w obiekcie żądania. Za pierwszym razem pętla kończy się z ustawioną flagą statusu uruchomienia obiektu żądania (jako wartość logiczna true), co kończy uruchamianie.
Domyślną klasą uruchamiającą jest
Zend_Controller_Dispatcher_Standard
. Definiuje ona
kontroler jako CamelCasedClasses zakończone słowem
Controller, oraz metody akcji jako camelCasedMethods
zakończone słowem Action:
SomeFooController::barAction
. W tym przypadku,
odpowiadałoby to kontrolerowi o nazwie somefoo
oraz akcji o nazwie bar
.
Zend_Controller_Action
jest podstawowym
komponentem kontrolera. Każdy kontroler jest pojedynczą
klasą, która rozszerza klasę Zend_Controller_Action
,
a ta klasa posiada metody które są akcjami.
Zend_Controller_Response_Abstract
definiuje
podstawową klasę odpowiedzi używaną do zbierania i
zwracania odpowiedzi z kontrolerów akcji. Zbiera ona
zarówno nagłówki jak i zawartość treści, oraz z tego
względu, że implementuje metodę __toString()
,
może być bezpośrednio wyświetlona w celu wysłania wszystkich
nagłówków i całej zawartości na raz.
Domyślną klasą odpowiedzi jest
Zend_Controller_Response_Http
, która jest
odpowiednia do użycia w środowisku HTTP.
Przestrzeń systemu Zend_Controller
jest stosunkowo
prosta. Żądanie jest odbierane przez obiekt Zend_Controller_Front
,
który wywołuje Zend_Controller_Router_Rewrite
w celu określenia
kontrolera (i akcji w tym kontrolerze) do uruchomienia.
Zend_Controller_Router_Rewrite
rozkłada adres URI na części
w celu określenia nazwy kontrolera i akcji w żądaniu.
Wtedy Zend_Controller_Front
rozpoczyna pętlę uruchamiania
akcji z kontrolerów. Uruchamia Zend_Controller_Dispatcher_Standard
,
przekazując mu żądanie w celu uruchomienia kontrolera i akcji,
określonych w żądaniu (lub domyślnych). Gdy kontroler kończy działanie,
kontrola wraca do obiektu Zend_Controller_Front
. Jeśli
kontroler resetując status wykonania żądania wskazał kolejny kontroler,
który powinien być uruchomiony pętla kontynuuje działanie i kolejny
kontroler zostaje uruchomiony. W przeciwnym wypadku proces się
kończy.
Obiekt żądania jest prostym obiektem przekazywanym pomiędzy
obiektem Zend_Controller_Front
, routerem, dispatcherem
i klasami kontrolerów. Przechowuje on nazwę kontrolera, akcji
oraz parametrów, które mają być przekazane do akcji, tak samo jak
resztę środowiska żądania, które mogą być w środowisku HTTP, CLI
lub PHP-GTK.
Nazwa kontrolera jest dostępna za pomocą metod
getControllerName()
oraz
setControllerName()
.
Nazwa akcji kontrolera która ma być wywołana jest dostępna za
pomocą metod getActionName()
oraz
setActionName()
.
Parametry, które mają być przekazane do tej akcji są asocjacyjną
tablicą par klucz/wartość, ktore są dostępne za pomocą metod
getParams()
oraz setParams()
, lub
pojedynczo za pomocą metod getParam()
oraz
setParam()
.
Zależnie od typu żądania, może być dostępnych więcej metod.
Domyślny obiekt żądania, Zend_Controller_Request_Http
,
ma na przykład metody do pobierania zażądanego adresu URI,
informacji o ścieżce, parametrów $_GET oraz $_POST itp.
Obiekt żądania jest przekazywany do kontrolera frontowego, lub jeśli nie istnieje zostaje utworzona jego instancja na początku procesu uruchomiania, zanim przeprowadzany jest routing. Jest on przekazywany przez każdy obiekt w łańcuchu uruchamiania.
Dodatkowo obiekt żądania jest użyteczny przy testowaniu. Programista może utworzyć środowisko żądania, włączając w to kontroler, akcję, parametry, URI itp. i przekazać obiekt żądania do kontrolera frontowego aby testować działanie aplikacji. Gdy do tego dołożymy obiekt odpowiedzi, precyzyjne testowanie jednostkowe aplikacji MVC staje się możliwe.
Zanim zbudujesz swój pierwszy kontroler, powinieneś zrozumieć jak
działa proces routingu który jest zaimplementowany jako
Zend_Controller_Router_Rewrite
. Pamiętaj, że przestrzeń
działania jest podzielona na routing, który ma miejsce tylko raz
oraz na proces dispatchingu, który odbywa się w pętli.
Zend_Controller_Front
wywołuje
Zend_Controller_Router_Rewrite
(lub inny zarejestrowany
router) aby zmapować adres URI do kontrolera oraz do akcji wewnątrz
kontrolera. Zend_Controller_Router_Rewrite
pobiera
adres URI z obiektu żądania i przekazuje go do obiektów tras w jego
łańcuchu; domyślnie używa on
Zend_Controller_Router_Route_Module
do dopasowania
adresów URL. Obiekt trasy następnie rozkłada URL na części aby
określić nazwę kontrolera, akcji i inne parametry z adresu URL a
następnie ustawia je w obiekcie żądania.
Zend_Controller_Router_Route_Module
używa bardzo
prostego mapowania w celu określenia nazwy kontrolera oraz akcji
wewnątrz kontrolera:
http://framework.zend.com/controller/action/
Pamiętaj, że powyżej pierwsza część adresu jest nazwą kontrolera, a druga część jest zawsze nazwą akcji.
Opcjonalnie w adresie URI mogą być zdefiniowane parametry które zostaną przekazane do kontrolera. Przyjmują one postać par klucz/wartość:
http://framework.zend.com/controller/action/key1/value1/
Jeśli w adresie URI brakuje informacji o kontrolerze lub akcji
Zend_Controller_Dispatcher_Standard
spróbuje pobrać
wartości z parametrów obiektu żądania i jeśli nie zostaną w nim
znalezione, użyje domyślnych wartości. Zarówno dla kontrolera jak i
dla akcji domyślną wartością jest "index
". Pokazuje to
ten przykład:
http://framework.zend.com/roadmap/future/ Kontroler: roadmap Akcja : future http://framework.zend.com/roadmap/ Kontroler: roadmap Akcja : index http://framework.zend.com/ Kontroler: index Akcja : index
Elastyczność | |
---|---|
Jeśli chcesz bardziej elastyczne możliwości, możesz sprawdzić dokumentację Rewrite Routera. |
Nazwa kontrolera, nazwa akcji w kontrolerze i parametry opcjonalne
są ustawione w obiekcie żądania. Kiedy kontroler frontowy
Zend_Controller_Front
wchodzi w pętlę uruchomieniową,
obiekt żądania będzie przekazany do obiektu
Zend_Controller_Dispatcher_Standard
.
Uruchamianie jest procesem pobierania obiektu żądania,
Zend_Controller_Request_Abstract
, wyciągania z niego
nazwy kontrolera, nazwy akcji oraz opcjonalnych parametrów zawartych
w nim, następnie tworzenia instancji kontrolera i uruchamiania akcji
tego kontrolera. Jeśli kontroler lub akcja nie zostaną znalezione,
zostaną użyte wartości domyślne. Zend_Controller_Dispatcher_Standard
ustawi wartość index
zarówno dla kontrolera jak i akcji,
ale pozwala programiście zmienić domyślne wartości używając metod
setDefaultController()
oraz
setDefaultAction()
.
Uruchamianie działa w pętli w kontrolerze frontowym. Zanim zacznie się uruchamianie, kontroler frontowy sprawdza żądanie aby określić nazwę kontrolera, akcji oraz opcjonalne parametry. Wtedy wchodzi w pętlę urchomieniową, uruchamiając żądanie.
Na początku każdej iteracji, w obiekcie żądania ustawiana jest flaga określająca czy akcja została uruchomiona. Jeśli akcja lub metoda pre/postDispatch plugina zresetuje tę flagę, pętla uruchamiania będzie kontynuowana i spróbuje uruchomić żądanie ponownie. Zmieniając nazwę kontrolera oraz/lub akcji w żądaniu i resetując flagę, programista może zdefiniować łańcuch żądań do uruchomienia.
Metodą kontrolera akcji, która kontroluje takie uruchamianie jest
_forward()
; wywołaj tę metodę w metodach
pre/postDispatch() lub w metodach akcji podając nazwę kontrolera,
akcji i opcjonalnie dodatkowe parametry które chcesz wysłać do
nowej akcji:
public function myAction() { // coś przetwarzaj... // przenieś do innej akcji, FooController::barAction(), w obecnym // module: $this->_forward('bar', 'foo', null, array('baz' => 'bogus')); }
Obiekt odpowiedzi jest logiczną parą dla obiektu żądania. Jego
zadaniem jest zebranie zawartości oraz/lub nagłówków aby mogły
być one zwrócone wszystkie na raz. Dodatkowo, kontroler frontowy
przekaże wszystkie złapane wyjątki do obiektu odpowiedzi, pozwalając
programiście wdzięcznie obsłużyć wyjątki. Ta funkcjonalność może
być nadpisana przez ustawienie
Zend_Controller_Front::throwExceptions(true)
:
$front->throwExceptions(true);
Aby wysłać obiekt odpowiedzi, włączając w to nagłówki, użyj metody
sendOutput()
.
$response->sendOutput();
Programiści powinni użyć obiektu odpowiedzi w ich kontrolerach akcji. Zamiast bezpośrednio wyświetlać dane wyjściowe i wysyłać nagłowki powinni przekazywać je do obiektu odpowiedzi:
// Wewnątrz akcji kontrolera: // Ustaw nagłówek $this->getResponse() ->setHeader('Content-Type', 'text/html') ->appendBody($content);
Dzięki temu wszystkie nagłówki są wysyłane na raz, zaraz przed wyświetleniem zawartości.
To czy wyjątek wystąpił w aplikacji możesz sprawdzić za pomocą metody
isException()
, a odebrać wyjątek możesz używając
metody getException()
. Dodatkowo możesz
stworzyć własny obiekt odpowiedzi, który może przekierowywać do
stron błędów, zapisywać informacje o wyjątku, ładnie formatować
informacje o wyjątku (dla potrzeb programistycznych) itp.
Możesz odebrać obiekt odpowiedzi po wywołaniu metody dispatch(), lub powodując aby kontroler frontowy zwrócił obiekt odpowiedzi zamiast renderowania danych wyjściowych.
// odbierz obiekt po uruchomieniu: $front->dispatch(); $response = $front->getResponse(); if ($response->isException()) { // zaloguj, wyślij mailem itp. } // lub spowoduj aby metoda dispatch() zwróciła obiekt odpowiedzi $front->returnResponse(true); $response = $front->dispatch(); // coś przetwarzaj... // ostatecznie wyświetl odpowiedź $response->sendOutput();
Domyślnie komunikaty wyjątków nie są wyświetlane. Te zachowanie może
być zmienione przez wywołanie metody renderException()
,
lub włączenie w kontrolerze frontowym opcji throwExceptions(), tak
jak pokazano niżej:
$response->renderExceptions(true); $front->dispatch($request, $response); // lub: $front->returnResponse(true); $response = $front->dispatch(); $response->renderExceptions(); $response->sendOutput(); // lub: $front->throwExceptions(true); $front->dispatch();