Zarządzanie adresami URL
Pełne zarządzanie adresami URL w ramach aplikacji webowej składa się z dwóch
aspektów. Pierwszy, gdy ze strony użytkownika pojawia się żądanie w formacie
URL. Wówczas aplikacja musi przetworzyć je do postaci zrozumiałych dla siebie
parametrów. W drugim przypadku aplikacja musi dostarczyć mechanizmu tworzenia
takich adresów URL, by były one zrozumiałe dla samej aplikacji.
W przypadku aplikacji Yii jest to dokonywane przy pomocy CUrlManager.
Tworzenie adresów URL
Pomimo, że adresy URL mogą być sztywno zapisane w widokach kontrolera,
bardziej elastycznym sposobem jest ich dynamiczne tworzenie:
$url=$this->createUrl($route,$params);
gdzie $this odnosi się do instancji kontrolera; $route określa trasę
route wywołania; $params jest listą
parametrów GET, dodaną do adresu URL.
Domyślnie adres URL utworzony przez createUrl
jest w tak zwanym formacie get. Przykładowo, dla zadanych $route='post/read'
i $params=array('id'=>100), uzyskamy następujący URL:
/index.php?r=post/read&id=100
parametry pojawiają się w wywołaniu w postaci listy wyrażeń Name=Value,
złączonych znakiem ampersand (&). Parametr r reprezentuje żądanie
route. Ten format URL nie jest zbyt
przyjazny użytkownikowi, ponieważ wymaga kilku nieczytelnych znaków.
Możemy sprawić by powyższy URL prezentował się czytelniej i był bardziej
zrozumiały używając adresu formatowanego ukośnikami (ang. path), który
eliminuje kwerendę i umieszcza parametry GET na ścieżce adresu URL:
/index.php/post/read/id/100
Aby zmienić format adresów URL musimy skonfigurować komponent aplikacji
urlManager tak, by createUrl
mógł automatycznie przełączyć się na nowy format i by aplikacja mogła zrozumieć
nowe adresy URL:
array(
......
'components'=>array(
......
'urlManager'=>array(
'urlFormat'=>'path',
),
),
);
Zauważ, że nie musimy definiować klasy komponentu urlManager
ponieważ jest on wstępnie zadeklarowana jako CUrlManager w CWebApplication.
Wskazówka: URL wygenerowany przy pomocy metody createUrl
jest adresem względnym. Aby uzyskać pełny adres wystarczy poprzedzić adres względny
Yii::app()->request->hostInfo lub wywołać metodę createAbsoluteUrl.
Przyjazne adresy URL
Gdy używany jest URL formatowany ukośnikami (ang. path) możemy zdefiniować
pewne reguły tworzenia URL tak, by adres był jeszcze bardziej przyjazny użytkownikowi.
Przykładowo możemy generować adres tak krótki jak /post/100, zamiast długiego
/index.php/post/read/id/100. Reguły tworzenia adresów URL używane są przez
CUrlManager, zarówno do celów tworzenia, jak i przetwarzania adresów URL.
Aby utworzyć te reguły musimy skonfigurować właściwość rules
komponentu aplikacji urlManager:
array(
......
'components'=>array(
......
'urlManager'=>array(
'urlFormat'=>'path',
'rules'=>array(
'pattern1'=>'route1',
'pattern2'=>'route2',
'pattern3'=>'route3',
),
),
),
);
Opisywane reguły definiowane są w tablicy przechowującej pary wyrażeń postaci
wzorzec-trasa, każda z takich par odpowiada jednej regule. Wzorzec reguły jest łańcuchem
używanym w celu dopasowania części informacyjnej adresu URL do wzorca.
Trasa powinna odnosić się do poprawnej trasy kontrolera.
Poza powyższym formatem wzorzec-trasa, regułą może być również określona poprzez
dostosowania opcji w następujący sposób:
'pattern1'=>array('route1', 'urlSuffix'=>'.xml', 'caseSensitive'=>false)
W powyższym kodzie, tablica zawiera listę opcji, które można dostosowywać. Od wersji 1.1.0
następujące opcje są dostępne:
urlSuffix: sufiks adresu URL używany specjalnie dla danej reguły.
Domyślnie posiada wartość null, oznaczającą że używana jest wartość CUrlManager::urlSuffix.
caseSensitive: określa czy reguła uwzględnia wielkość liter. Domyślnie
posiada wartość null, co oznacza, że używana jest wartość CUrlManager::caseSensitive.
defaultParams: domyślne parametry GET (nazwa=>wartość) które ustanawia
dana reguła. Kiedy dana reguła używana jest do parsowania przychodzącego żądania, wartości zadeklarowane
w tej właściwości zostaną wstrzyknięte do $_GET.
matchValue: określa czy wartości parametru GET powinny pasować do odpowiadających
im podwzorców w regule, kiedy tworzony jest URL. Domyślnie przyjmuje wartość null, oznaczającą używanie wartości
CUrlManager::matchValue. Jeśli wartość ta wynosi false, oznacza to, że reguła będzie używana do tworzenia URL
jeśli jej trasa i nazwy parametrów są zgodnie z podanymi. Jeśli właściwość ta przyjmuje wartość tryu, wtedy
podane wartości parametru muszą również pasować do odpowiadających parametrowi podwzorców. Zauważ, że
ustawienie tej pozycji na true może obniżyć wydajność.
Używanie nazwanych parametrów
Reguła może być powiązana z kilkoma parametrami GET. Te parametry pojawiają
się we wzorcu reguły jako specjalne znaczniki o formacie:
<ParamName:ParamPattern>
gdzie ParamName określa nazwe parametru GET, a opcjonalny ParamPattern definiuje
wyrażenie regularne, które ma być używane do badania dopasowania wartości parametru
GET. W przypadku gdy pominięto ParamPattern, oznacza to, że parametr ten może zawierać
wszystkie znaki poza ukośnikiem /. Gdy tworzymy adres URL znaczniki tych parametrów
zostaną zastąpione odpowiednimi wartościami parametru GET; podczas przetwarzania
adresu URL odpowiednie parametry GET zostaną wypełnione wynikami tego przetwarzania.
Pokażmy kilka przykładów by wyjaśnić jak działają reguły adresów URL. Zakładamy,
że nasz zestaw reguł składa się z trzech, widocznych poniżej:
array(
'posts'=>'post/list',
'post/<id:\d+>'=>'post/read',
'post/<year:\d{4}>/<title>'=>'post/read',
)
Wywołanie $this->createUrl('post/list') tworzy /index.php/posts.
Stosowana jest pierwsza reguła.
Wywołanie $this->createUrl('post/read',array('id'=>100)) generates
/index.php/post/100. Zastosowana została druga reguła.
Wywołanie $this->createUrl('post/read',array('year'=>2008,'title'=>'a
sample post')) tworzy /index.php/post/2008/a%20sample%20post. Zastosowana
została trzecia reguła.
Wywołanie $this->createUrl('post/read') tworzy
/index.php/post/read. Żadna z reguł nie została użyta.
Podsumowując: gdy używamy createUrl do generowania
adresów URL, trasa i parametry GET przekazywane do tej metody umożliwiają
wybór reguły, która ma być zastosowana. Jeżeli każdy z parametrów powiązanych
z pewną reguła występuje również wśród parametrów GET przekazywanych do
createUrl i jeżeli trasa zawarta w tej regule pasuje
do trasy w parametrach wywołania metody, to ta reguła będzie użyta
do wygenerowania adresu URL.
Jeżeli parametrów GET przekazywanych do metody createUrl
jest więcej niż wymaga jakakolwiek reguła, nadmiarowe parametry pojawią się
w ciągu argumentów tej metody. Przykładowo: jeżeli wywołamy
$this->createUrl('post/read',array('id'=>100,'year'=>2008)) otrzymalibyśmy
/index.php/post/100?year=2008. Po to, by te dodatkowe parametry pojawiły się
w części informacyjnej adresu, powinniśmy dodać /* do reguły. Wówczas, używając
reguły post/<id:\d+>/*, możemy uzyskać adres URL postaci
/index.php/post/100/year/2008.
Jak wcześniej wspominaliśmy innym zastosowaniem reguł URL jest przetwarzanie
wywoływanych adresów URL. Jest to oczywiście proces odwrotny do tworzenia
adresów. Np. gdy użytkownik zgłasza żądanie adresu /index.php/post/100,
zastosowanie będzie miała druga reguła z przykłady wyżej. Spowoduje to
rozłożenie żądania na trasę post/read i parametr GET array('id'=>100)
(dostępny poprzez $_GET).
Uwaga: korzystanie z reguł URL obniża wydajność aplikacji. Dzieje się tak
ponieważ CUrlManager przetwarzając wywoływany URL porównuje go z każdą regułą,
aż nie trafi na odpowiednią. Im większa ilość reguł, tym większy mają one wpływ na wydajność.
Z tego względu w mocno obciążanych aplikacjach webowych należy minimalizować użycie reguł URL.
Parametryzowane trasy
Poczynając od wersji 1.0.5, możemy odnosić się do nazwanych parametrów w części reguły
związanej z trasą. Pozwala to zastosować regułę do wielu tras w oparciu o spełniane kryterium.
Może to pomóc zredukować ilość reguł potrzebnych dla aplikacji i przez to zwiększyć
ogólną wydajność.
Będziemy używać następujących przykładowych reguły aby zilustrować jak parametryzować
trasę za pomocą nazwanych parametrów:
array(
'<_c:(post|comment)>/<id:\d+>/<_a:(create|update|delete)>' => '<_c>/<_a>',
'<_c:(post|comment)>/<id:\d+>' => '<_c>/read',
'<_c:(post|comment)>s' => '<_c>/list',
)
W powyższym kodzie, uzyliśmy dwóch nazwancyh parametrów w cześci reguły odnoszącej się
do strasy: _c oraz _a. Pierwszy parametr odpowiada ID kontrolera posiadającym wartość post lub comment,
podczas gdy drugi odpowiada ID akcji, która może mieć wartość create, update lub delete.
Możesz nazywać parametry dowolnie, dopóki ich nazwy nie konfliktują z parametrami GET
znajdującymi się w URLach.
Używając powyższych reguł, URL /index.php/post/123/create zostanie sparsowany na
trasę post/create z parametrem GET id=123. A biorąc pod uwagę trasę
comment/list oraz parametr GET page=2, możemy stworzyć URL
/index.php/comments?page=2.
Parametryzowanie nazw hostów
Zaczynając od wersji 1.0.11, możliwym jest dołaczanie nazwy hosta do reguł parsowania
oraz tworzenia URLi. Można wyodrębnić część nazwy hosta do parametru GET. Na przykład,
adres URL http://admin.example.com/en/profile może zostać sparsowany do parametrów
GET user=admin oraz lang=en. Z drugiej strony, reguły z nazwą hosta mogą zostać użyte
do utworzenia URLi z parametryzowanymi nazwami hostów.
W celu używania parametryzowanych nazw hostów, po prostu zadeklaruj regułę URL z
informacją o hoście, np:
array(
'http://<user:\w+>.example.com/<lang:\w+>/profile' => 'user/profile',
)
Powyższy przykład mówi, iż pierwszy segment w nazwie hosta powinien być traktowany jako
parametr user, zaś pierwszy segment w ścieżce powinien być parametrem lang.
Reguła odpowiada trasie user/profile.
Zauważ, że CUrlManager::showScriptName nie będzie działało, jeśli URL zostanie
utworzony za pomocę reguły z parametryzowaną nazwą hosta.
Zauważ, że reguła ze sparametryzowaną nazwą hosta NIE POWINNA zawierać podkatalogu
jeśli aplikacja znajduje się w podkatalogu katalogu głównego www.
Na przykład, jeśli aplikacja znajduje się w
http://www.example.com/sandbox/blog, wtedy wciąż powinniśmy używać tej samej reguły URL
jak opisana powyżej bez podkatalogu sandbox/blog.
Ukrywanie index.php
Czyszcząc adresy URL możemy zrobić jeszcze jedną rzecz więcej ukrywając
w adresie URL skrypt startowy index.php. To wymaga od nas skonfigurowania
web serwera oraz komponentu aplikacji urlManager.
Po pierwsze musimy skonfigurować web serwer tak, by adres URL pozbawiony
skryptu wejściowego mógł być zawsze obsługiwany z uwzględnieniem skryptu.
W przypadku serwera HTTP Apache może to być zrealizowane poprzez
włączenie tzw. mechanizmu nadpisywania URL (ang. URL rewriting engine)
i zdefiniowanie kilku reguł nadpisywania. Możemy stworzyć plik /wwwroot/blog/.htaccess
z następującą zawartością. Zauważ, że ta sama zawartość może zostać umieszczona
w pliku konfiguracji Apache'a wewnątrz elementu Directory dla /wwwroot/blog.
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on
# jeżeli katalog lub plik istnieje użyj ich bezpośrednio
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# w przeciwnym razie przekieruj na index.php
RewriteRule . index.php
Później konfigurujemy wspomnianą właściwość showScriptName
komponentu urlManager przypisując jej wartość false.
Teraz możemy wywołać $this->createUrl('post/read',array('id'=>100)), otrzymując URL
/post/100. I co ważniejsze ten adres URL będzie poprawnie rozpoznany przez twoją
aplikację webową.
Pozorowany sufiks adresu URL
Możemy również dodawać pewne sufiksy do adresów URL. Na przykład możemy uzyskać
/post/100.html zamiast /post/100. To sprawia, że wygląda on bardziej jak URL
do strony statycznej. Aby to zrobić po prostu skonfiguruj komponent
urlManager ustawiając jego właściwość
urlSuffix na taki sufiks, jaki ci odpowiada.
$Id: topics.url.txt 2229 2010-06-25 19:57:54Z poppitypop@gmail.com $