Zend Framework zapewnia kilka alternatyw dla domyślnych klas, włączając w to alternatywne obiekty żądania, routery oraz obiekty odpowiedzi.
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
.
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 |
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.
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();
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ść
|
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")
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')) );
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 |
$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.
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.
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. |
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”).
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 |
---|---|
|
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();
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', $loginRoute);
In addition to the default and static route types, a Regular Expression route type is available. This route offers more power and flexibility than the others, but at a slight cost of performance, due to its use of the PCRE engine.
Zend_Controller_Router_Route_Regex
provides a
regex-based route type for use with the rewrite router. Some
usage rules to consider:
It uses the #
character for a delimiter. This
means that you will not need to escape forward slashes
('/'), but will need to escape hash characters ('#').
Line start and line end anchors ('^' and '$', respectively) are automatically pre- and appended to all expressions. Thus, you should not use these in your regular expressions. Also, it means that you should write your expressions to match the entire URL. As an example, given the URL 'http://example.com/foo/bar/baz/bat', if you simply wish to match 'foo/bar', you should write your expression as 'foo/bar(/.*)?'.
The leading and trailing slash are trimmed prior to a match. As a result, matching the URL "http://example.com/foo/bar/" would involve a regex of "foo/bar".
One strength of using regular expressions is the ability to
capture matching segments for use later.
Zend_Controller_Router_Regex_Route
makes use of
this capability in two ways, either:
Setting parameters in the request object as match index (integer) => match. As an example:
<?php // Anything after /foo/bar in the path would be retrieved via the key '1' in the // request object: $route = new Zend_Controller_Router_Route_Regex( 'foo/bar(/.*)?', array('controller' => 'foo', 'action' => 'bar') ); // After routing: $fooPath = $request->getParam('1');
Using a map list from the third parameter passed to the route constructor to map indices to parameter keys. As an example:
<?php // Place anything after /foo/bar in the path into the 'fooPath' request key: $route = new Zend_Controller_Router_Route_Regex( 'foo/bar(/.*)?', array('controller' => 'foo', 'action' => 'bar'), array(1 => 'fooPath') );
As some examples of creating regex routes to use with your router:
// View archived blogs with urls like: // http://example.com/blog/archive/01-Using_the_Regex_Router.html // placing '01' as the 'id' key, and 'Using_the_Regex_Router' as the 'title' key $blogArchive = new Zend_Controller_Router_Route_Regex( 'blog/archive/(\d+)-(.*)\.html', array('controller' => 'blog', 'action' => 'view'), array(1 => 'id', 2 => 'title') ); $router->addRoute('blogArchive', $blogArchive); // View news items with urls like: // http://example.com/news/1193328 // placing '1193328' as the 'id' key $newsItem = new Zend_Controlelr_Router_Route_Regex( 'news/(\d+)', array('controller' => 'news', 'action' => 'view'), array(1 => 'id') ); $router->addRoute('newsItem', $newsItem);
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.
Przeanalizuj poniższy przykładowy plik INI:
[production] 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"
Powyższy plik INI może być odczytany przez obiekt
Zend_Config
w taki sposób:
$config = new Zend_Config_Ini('/path/to/config.ini', 'production'); $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
.
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.