7.4. Dostępne podklasy
Poprzedni | Rozdział 7. Zend_Controller | Następny

## 7.4. Dostępne podklasy

### 7.4.1. Wprowadzenie

Zend Framework zapewnia kilka alternatyw dla domyślnych klas, włączając w to alternatywne obiekty żądania, routery oraz obiekty odpowiedzi.

### 7.4.2. Zend_Controller_Request_Http

#### 7.4.2.1. Wprowadzenie

`Zend_Controller_Request_Http` zapewnia obiekt żądania do użycia w środowisku HTTP. Klasa `Zend_Controller_Request_Http` jest domyślną klasą żądania używaną przez `Zend_Controller_Dispatcher`.

#### 7.4.2.2. Dostęp do danych żądania

`Zend_Controller_Request_Http` obudowuje dostęp do odpowiednich wartości takich jak nazwa klucza i wartość dla zmiennych kontrolera i akcji routera, oraz do dodatkowych parametrów pobranych z adresu URI. Rozszerzając `Zend_Controller_Request_Http` dodatkowo pozwala na uzyskanie dostępu do wartości zawartych w superglobalnych tablicach jako do publicznych właściwości obiektu i zarządza obecnym bazowym adresem URL oraz adresem URL żądania. Superglobalne wartości nie mogą być ustawione w obiekcie żądania, zamiast tego użyj metod setParam/getParam aby ustawić lub odebrać parametry użytkownika.

| Dane superglobalne
Kiedy uzyskujemy dostęp do danych superglobalnych za pomocą klasy `Zend_Controller_Request_Http` jak do jej publicznych właściwości, ważne jest aby pamiętać, że nazwa właściwości (klucz tablicy superglobalnej) jest dopasowana do superglobalnych w określonej kolejności: 1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV.

Konkretne zmienne superglobalne mogą być alternatywnie dostępne za pomocą publicznej metody. Na przykład, wartość `$_POST['user']` może być dostępna przez wywołanie metody `getPost('user')` na obiekcie żądania.

#### 7.4.2.3. Bazowy Url oraz podkatalogi

Klasa `Zend_Controller_Request_Http` pozwala na użycie klasy Zend_Controller_Router_Rewrite w podkatalogach. Zend_Controller_Request_Http spróbuje automatycznie wykryć twój bazowy adres URL i ustawi go odpowiednio.

Na przykład jeśli twój plik `index.php` jest w podkatalogu nazwanym `/projects/myapp/index.php`, bazowy URL (bazowy adres przepisania) powinien być ustawiony na `/projects/myapp`. Ten łańcuch znaków zostanie obcięty z początu ścieżki zanim będą dopasowane jakiekolwiek trasy. To zwalnia z konieczności dołączania tego adresu do każdej z tras. Trasa `'user/:username'` dopasuje adresy URI takie jak `http://localhost/projects/myapp/user/martel` oraz `http://example.com/user/martel`.

| Detekcja URL jest wrażliwa na małe i duże litery
Automatyczna detekcja adresów URL jest wrażliwa na małe i duże litery, więc upewnij się, że adres URL zostanie dobrze dopasowany do nazwy podkatalogu w systemie plików (nawet w systemie Windows). Jeśli nie zostanie, zostanie wywołana akcja noRoute.

Jeśli bazowy adres URL jest wykrywany nieprawidłowo, możesz go nadpisać w obiekcie Zend_Http_Request wywołując metodę `setBaseUrl()` lub tą samą metodę klasy `Zend_Controller_Request_Http` lub klasy `Zend_Controller_Front`. Najłatwiejszy sposób to ustawienie tego w klasie `Zend_Controller_Front`, która przekaże to do obiektu żądania. Przykładowe użycie ustawiania własnego bazowego adresu URL:

    /**
     * Uruchom żądanie z własnym bazowym URL za pomocą Zend_Controller_Front.
     */
    $router     = new Zend_Controller_Router_Rewrite();
    $controller = Zend_Controller_Front::getInstance();
    $controller->setControllerDirectory('./application/controllers')
               ->setRouter($router)
               ->setBaseUrl('/projects/myapp'); // ustaw bazowy URL!
    $response   = $controller->dispatch();

### 7.4.3. Zend_Controller_Router_Rewrite

#### 7.4.3.1. Wprowadzenie

`Zend_Controller_Router_Rewrite` jest standardowym routerem we frameworku. Routing jest procesem pobrania adresu URI i rozłożenia go w celu ustalenia jaki kontroler i jaka akcja powinny otrzymać żądanie. Ta informacja o kontrolerze, akcji i opcjonalnych parametrach jest pakowana do obiektu `Zend_Controller_Request_Http`, który jest potem przetwarzany przez `Zend_Controller_Dispatcher_Standard`. Routing ma miejsce tylko raz: wtedy gdy żądanie jest po raz pierwszy otrzymane, przed wywołaniem pierwszego kontrolera.

`Zend_Controller_Router_Rewrite` jest zaprojektowany w celu uzyskania w czystym PHP takiej funkcjonalności jak w mod_rewrite. Jest to luźno wzorowane na routingu Ruby on Rails i nie wymaga żadnej wiedzy o przepisywaniu adresów przez serwer www. Jest to zaprojektowane w taki sposób, aby działało po dodaniu tylko jednej reguły mod_rewrite (jednej z poniższych):

    RewriteEngine on
    RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php

lub:

    RewriteEngine on
    RewriteCond %{SCRIPT_FILENAME} !-f
    RewriteCond %{SCRIPT_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1

Rewrite router może być także użyty z serwerem IIS, jeśli moduł Isapi_Rewrite jest zainstalowany jako rozszerzenie Isapi, z taką regułą przepisywania:

    RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css)$)[\w\%]*$)? /index.php [I]

| IIS Isapi_Rewrite
Jeśli używasz serwera IIS, to wartość `$_SERVER['REQUEST_URI']` nie istnieje lub jest pustym łańcuchem znaków. W takim wypadku, `Zend_Controller_Request_Http` spróbuje użyć wartości `$_SERVER['HTTP_X_REWRITE_URL']` ustawionej przez rozszerzenie Isapi_Rewrite.

Jeśli używasz serwera Lighttpd, poniższa reguła jest prawidłowa:

    url.rewrite-once = ( ".*\.(js|ico|gif|jpg|png|css)$" => "$0", "" => "/index.php")

#### 7.4.3.2. Użycie routera

Aby prawidłowo użyć rewrite routera musisz utworzyć jego instancję, zdefiniować jakieś trasy i przekazać ten obiekt do kontrolera. Poniższy kod pokazuje tą procedurę:

    /* Utwórz router */

    $router = $ctrl->getRouter(); // domyślnie zwraca rewrite router
    $router->addRoute(
    	'user',
    	new Zend_Controller_Router_Route('user/:username', array('controller' => 'user', 'action' => 'info'))
    );

#### 7.4.3.3. Podstawowe trasy

Sercem RewriteRoutera jest definicja tras określonych przez użytkownika. Trasy są tworzone przez wywołanie metody addRoute obiektu RewriteRouter i przekazanie do niej nowej instancji obiektu `Zend_Controller_Router_Route`:

    $router->addRoute('user', new Zend_Controller_Router_Route('user/:username'));

Pierwszy parametr jest nazwą trasy. Obecnie nie jest konieczne jego definiowanie, jednak będzie on używany w przyszłości w klasie pomocniczej widoku ułatwiającej łatwe generowanie adresów URL. Jeśli chcesz użyć wcześniej skonfigurowanej trasy, możesz ją odebrać za pomocą metody getRoute RewriteRoutera. Drugi parametr jest instancją `Zend_Controller_Router_Route`.

Pierwszy parametr konstruktora obiektu `Zend_Controller_Router_Route` jest trasą, która ma być dopasowana do adresu URL - na przykład powyższa trasa zostanie dopasowana do adresu `http://example.com/user/martel`. Dwukropek w trasie oznacza zmienną adresu URL. Po udanym dopasowaniu trasy, wartości wszystkich zdefiniowanych zmiennych zostaną przekazane do obiektu Zend_Controller_Request. Po tym będą one dostępne za pomocą metod Zend_Controller_Request::getParam oraz Zend_Controller_Action::_getParam. W naszym przykładzie parametr nazwany username będzie miał ustawioną wartość 'martel'.

| Odwrotne dopasowywanie
Trasy są dopasowywane w odwrotnej kolejności więc musisz pamiętać żeby podstawowe trasy były zdefiniowane na początku.

| Użycie znaków
Teraz obecna implementacja pozwala na użycie w nazwie zmiennej dowolnych znaków z wyjątkiem ukośnika (/), ale jest mocno zalecane używanie jedynie znaków, które są bezproblemowo obsługiwane ptzrz PHP. W przyszłości implementacja prawdopodobnie zostanie zmodyfikowana co mogłoby wprowadzić do twojego kodu błędy.

Są dwie specjalne zmienne które nie mogą być użyte w twoich trasach - ':controller' oraz ':action'. Te specjalne zmienne będą użyte aby znaleść kotroler oraz akcję w danym adresie URL. Zmienna ':action' zawsze musi być zdefiniowana w trasie lub jako domyślny parametr. Zmienna ':controller' będzie domyślnie ustawiona na IndexController jeśli nie będzie zdefiniowana.

| Specjalne zmienne
Nazwy tych specjalnych zmiennych mogą być inne, jeśli zdecydujesz zmienić je w obiekcie `Zend_Controller_Request_Http` za pomocą metod setControllerKey oraz setActionKey.

    $router->addRoute(
        'user', new Zend_Controller_Router_Route(':controller/:action')
    );

Jeśli skierujesz przeglądarkę na adres 'http://example.com/news/latest' ze zdefiniowaną powyższą trasą `Zend_Controller_Dispatcher` odwoła się do akcji latestAction z kontrolera NewsController.

#### 7.4.3.4. Domyślne wartości zmiennych

Każda zmienna w trasie może mieć wartość domyślną. Aby to zrobić, musisz przekazać drugi parametr do konstruktora `Zend_Controller_Router_Route`. Ten parametr jest tablicą z nazwami zmiennych jako kluczami i z wartościami, które mają być uznane za domyślne.

    $router->addRoute(
        'archive', new Zend_Controller_Router_Route('archive/:year', array('year' => 2006))
    );

Może nie jest wyraźnie widoczne to, że powyższa trasa dopasuje adresy URL takie jak 'http://example.com/archive/2005' oraz 'http://example.com/archive'. Ostatecznie zmienna year i tak będzie miała wartość 2006.

Powyższy przykład spowoduje jedynie przekazanie zmiennej oznaczającej rok do żądania. Nie będzie miał miejsca routing, ponieważ parametry oznaczające kontroler i akcję nie są ustawione. Aby było to bardziej użyteczne, musisz zapewnić prawidłową nazwę kontrolera i akcji jako domyślne wartości.

    $router->addRoute(
        'archive',
        new Zend_Controller_Router_Route('archive/:year', array('year' => 2006, 'controller' => 'archive', 'action' => 'show')
    );

Ta trasa spowoduje uruchomienie akcji showAction kontrolera ArchiveController.

#### 7.4.3.5. Wymagania zmiennych

Można dodać trzeci parametr do konstruktora `Zend_Controller_Router_Route` w którym będą ustawione wymagania zmiennych. Są one zdefiniowane jako wyrażenia regularne:

    $router->addRoute(
        'archive',
        new Zend_Controller_Router_Route('archive/:year', array('year' => 2006), array('year' => '\d+'))
    );

| Zachowanie routera
W przeciwieństwie do Ruby on Rails, RewriteRouter z ZF dopasuje trasę i użyje domyślnej gdy trzeci parametr zawierający wymagania zmiennych nie zostanie znaleziony. Więc adres URL 'http://example.com/archive/test' zostanie dopasowany do powyższej trasy, a rok zostanie ustawiony na 2006. Ta funkcjonalność może w przyszłości się zmienić, ponieważ w momencie pisania tej dokumentacji ta kwestia jest jeszcze uzgadniana.

#### 7.4.3.6. Bazowy adres URL i podkatalogi

Rewrite router może być użyty w podkatalogach, a bazowy adres URL zostanie automatycznie wykryty przez obiekt `Zend_Controller_Request_Http`.

Jeśli bazowy adres URL jest wykrywany nieprawidłowo, możesz go nadpisać w obiekcie `Zend_Controller_Request_Http` wywołując metodę `setBaseUrl()` (zobacz Sekcja 7.4.2.3, „Bazowy Url oraz podkatalogi”).

#### 7.4.3.7. Domyślne trasy

Zend_Controller_Router_Rewrite jest skonfigurowany z jedną domyślną trasą. Dopasuje on adresy w postaci `'controller/action'` . Dodatkowo, nazwa modułu może być określoa jako pierwszy element ścieżki, pozwalając na użycie adresów w postaci `'module/controller/action`. Ostatecznie domyślnie dopasuje dodatkowe parametry dołączone do adresu URI.

Kilka przykładów doopasowania tras:

    // Zakładając poniższe:
    // $ctrl->setControllerDirectory(array(
    //     'default' => '/path/to/default/controllers',
    //     'news'    => '/path/to/blog/controllers',
    //     'blog'    => '/path/to/blog/controllers'
    // ));

    Tylko moduł:
    http://example/news
        module == news

    Nieprawidłowy moduł mapuje do nazwy kontrolera:
    http://example/foo
        controller == foo

    Moduł oraz kontroler:
    http://example/blog/archive
        module     == blog
        controller == archive

    Moduł, kontroler oraz akcja:
    http://example/blog/archive/list
        module     == blog
        controller == archive
        action     == list

    Moduł, kontroler, akcja oraz parametry:
    http://example/blog/archive/list/sort/alpha/date/desc
        module     == blog
        controller == archive
        action     == list
        sort       == alpha
        date       == desc

Domyślną trasą jest obiekt `Zend_Controller_Router_Route_Module` utworzony bez żadnych domyślnych parametrów:

    // Trasa kompatybilna z pierwszą wersja routera
    $compat = new Zend_Controller_Router_Route_Module();
    $this->addRoute('default', $compat);

| Dopasowanie adresów URI
`Zend_Controller_Router_Rewrite` jest skonfigurowany z kompatybilnością wsteczną. Automatycznie dopasuje kontroler i akcję z adresu wraz z dodatkowymi parametrami. Dodatkowe parametry nie wymagają dodawania nowych tras, o ile nie chcemy zdefiniować dla nich domyślnych wartości lub wymagań. Te dodatkowe parametry będą dostępne za pomocą metody `Zend_Controller_Action::_getParam()`.

Jeśli nie potrzebujesz domyślnych tras w swoim schemacie routingu, możesz je usunąć używając metody `removeDefaultRoutes()`:

    // Usuwa domyślną trasę
    $router->removeDefaultRoutes();

#### 7.4.3.8. Trasy statyczne

Wszystkie powyższe przykłady używają dynamicznych tras -- tras, które są dopasowywane do szablonów. Czasem jakaś trasa jest niezmienna, a ciągłe sprawdzanie wyrażenia regularnego może być zabójcze dla serwera. Rozwiązaniem takiej sytuacji jest użycie statycznych tras:

    $loginRoute = new Zend_Controller_Router_Route_Static('login', array('controller' => 'login', 'action' => 'form'));
    $router->addRoute('login', $static);

#### 7.4.3.9. Użycie Zend_Config z RewriteRouterem

Czasem wygodniej jest uaktualnić plik konfiguracyjny z nowymi trasami niż zmieniać kod. Jest to możliwe za pomocą metody `addConfig()`. Zasadniczo tworzysz konfigurację kompatybilną z Zend_Config, a w kodzie odczytujesz ją i przekazujesz ją do RewriteRoutera.

    /**
     * Przykładowy plik INI:
     * routes.archive.route = "archive/:year/*"
     * routes.archive.defaults.controller = archive
     * routes.archive.defaults.action = show
     * routes.archive.defaults.year = 2000
     * routes.archive.reqs.year = "\d+"
     *
     * routes.news.type = "Zend_Controller_Router_Route_Static"
     * routes.news.route = "news"
     * routes.news.defaults.controller = "news"
     * routes.news.defaults.action = "list"
     */
    $config = new Zend_Config_Ini($file);
    $router = new Zend_Controller_Router_Rewrite();
    $router->addConfig($config, 'routes');

W powyższym przykładzie, nakazujemy routerowi użyć sekcji 'routes' pliku INI aby użyć tras zdefiniowanych w tym pliku. Każdy element pierwszego poziomu w tej sekcji będzie użyty do zdefiiniowania nazwy trasy; powyższy przekład definiuje trasy 'archive' oraz 'news'. Wymagane jest aby każda trasa miała określony przynajmniej parametr 'route' i jeden lub więcej parametrów 'defaults'; opcjonalnie mogą być zdeiniowane parametry 'reqs' (skrót 'required'). Wszystkie te parametry odpowiadają trzem argumentom przekazywanym do obiektu `Zend_Controller_Router_Route_Interface` Klucz opcji 'type' może być użyty aby określić typ klasy, która ma być użyta dla danej trasy; domyślnie używana jest klasa `Zend_Controller_Router_Route`. W powyższym przykładzie, trasa 'news' jest zdefiniowana aby używała `Zend_Controller_Router_Route_Static`.

### 7.4.4. Zend_Controller_Response_Http

`Zend_Controller_Response_Http` jest obiektem odpowiedzi odpowiednim do użycia w środowisku HTTP. Zawiera metody do ustawiania, odbierania i czyszczenia nagłówków, a metoda `__toString()` wysyła wszystkie nagłówki na raz przed wysłaniem zawartości odpowiedzi.

Metoda `setHeader()` przyjmuje dwa argumenty, typ nagłówka oraz wartość nagłówka. Trzeci opcjonalny parametr, jeśli jest przekazany i ma wartość true, spowoduje, że nowy nagłówek zastąpi inne zarejestrowane nagłówki o tym typie.

### 7.4.5. Zend_Controller_Response_Cli

`Zend_Controller_Response_Cli` jest obiektem odpowiedzi odpowiednim do użycia w środowisku CLI. Nie ma on metod do obsługi nagłówków i w prosty sposób zwraca całą zawartość gdy wywoływana jest metoda `__toString()`.

Poprzedni | Początek rozdziału | Następny
7.3. Rozszerzanie | Spis treści | 7.5. Action Controllers