mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-12 02:56:55 +01:00
422 lines
18 KiB
Plaintext
422 lines
18 KiB
Plaintext
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:
|
|
|
|
~~~
|
|
[php]
|
|
$url=$this->createUrl($route,$params);
|
|
~~~
|
|
|
|
gdzie `$this` odnosi się do instancji kontrolera; `$route` określa trasę
|
|
[route](/doc/guide/basics.controller#route) wywołania; `$params` jest listą
|
|
parametrów `GET`, dodaną do adresu URL.
|
|
|
|
Domyślnie adres URL utworzony przez [createUrl|CController::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](/doc/guide/basics.controller#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|CWebApplication::urlManager] tak, by [createUrl|CController::createUrl]
|
|
mógł automatycznie przełączyć się na nowy format i by aplikacja mogła zrozumieć
|
|
nowe adresy URL:
|
|
|
|
~~~
|
|
[php]
|
|
array(
|
|
......
|
|
'components'=>array(
|
|
......
|
|
'urlManager'=>array(
|
|
'urlFormat'=>'path',
|
|
),
|
|
),
|
|
);
|
|
~~~
|
|
|
|
Zauważ, że nie musimy definiować klasy komponentu [urlManager|CWebApplication::urlManager]
|
|
ponieważ jest ona wstępnie zadeklarowana jako [CUrlManager] w [CWebApplication].
|
|
|
|
> Wskazówka: URL wygenerowany przy pomocy metody [createUrl|CController::createUrl]
|
|
jest adresem względnym. Aby uzyskać pełny adres wystarczy poprzedzić adres względny
|
|
`Yii::app()->request->hostInfo` lub wywołać metodę [createAbsoluteUrl|CController::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|CUrlManager::rules]
|
|
komponentu aplikacji [urlManager|CWebApplication::urlManager]:
|
|
|
|
~~~
|
|
[php]
|
|
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](/doc/guide/basics.controller#route) powinna odnosić się do poprawnej trasy kontrolera.
|
|
|
|
Poza powyższym formatem wzorzec-trasa, reguła może być również określona poprzez
|
|
dostosowanie opcji w następujący sposób:
|
|
|
|
~~~
|
|
[php]
|
|
'pattern1'=>array('route1', 'urlSuffix'=>'.xml', 'caseSensitive'=>false)
|
|
~~~
|
|
|
|
Poczynając od wersji 1.1.7, można używać następującego formatu ( wzorzec jest
|
|
określony w postaci elementu tablicy ) co pozwala określić kilka reguł
|
|
z tym samym wzorcem:
|
|
|
|
~~~
|
|
[php]
|
|
array('route1', 'pattern'=>'pattern1', 'urlSuffix'=>'.xml', 'caseSensitive'=>false)
|
|
~~~
|
|
|
|
W powyższym kodzie, tablica zawiera listę dodatkowych opcji dla reguły.
|
|
Dostępne opcje zostały wyjaśnione poniżej:
|
|
|
|
- [pattern|CUrlRule::pattern]: wzorzec używany do dopasowywania oraz tworzenia URLi.
|
|
Opcja ta jest dostępna od wersji 1.1.7
|
|
|
|
- [urlSuffix|CUrlRule::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|CUrlRule::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|CUrlRule::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|CUrlRule::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ść true, 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ść.
|
|
|
|
- [verb|CUrlRule::verb]: metody HTTP (np. `GET`, `POST`, `DELETE`), do których ta reguła ma być dopasowana
|
|
w celu używania jej do analizowania aktualnego żądania. Domyślnie null, co oznacza, że reguła jest dopasowywana
|
|
do każdej metody HTTP. Jeżeli reguła ma być dopasowana do wielu metod, ich nazwy muszą być rozdzielone przecinkami.
|
|
Jeżeli reguła nie jest dopasowana do określonej metody (metod), zostanie ona pominięta podczas analizowania żądania.
|
|
Opcja ta jest używana jedynie do analizowania żądania i dostarczona jest głównie w celu wsparcia RESTful URL.
|
|
Opcja ta jest dostępna od wersji 1.1.7.
|
|
|
|
- [parsingOnly|CUrlRule::parsingOnly]: określa czy reguła jest używana jedynie do analizowania żądania.
|
|
Domyślnie przyjmuje wartość false, co oznacza, że reguła jest używana zarówno do analizowania adresów URL jak i ich tworzenia.
|
|
Opcja ta jest dostępna od wersji 1.1.7.
|
|
|
|
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:
|
|
|
|
~~~
|
|
[php]
|
|
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))` tworzy
|
|
`/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|CController::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|CController::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|CController::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ładu 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
|
|
---------------------
|
|
|
|
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:
|
|
|
|
~~~
|
|
[php]
|
|
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, użyliśmy dwóch nazwanych parametrów w części reguły odnoszącej się
|
|
do trasy: `_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
|
|
----------------------------
|
|
|
|
Możliwe jest dołączanie 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:
|
|
|
|
~~~
|
|
[php]
|
|
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|CWebApplication::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](http://httpd.apache.org/) 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`.
|
|
|
|
~~~
|
|
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|CUrlManager::showScriptName]
|
|
komponentu [urlManager|CWebApplication::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|CWebApplication::urlManager] ustawiając jego właściwość
|
|
[urlSuffix|CUrlManager::urlSuffix] na taki sufiks, jaki ci odpowiada.
|
|
|
|
Używanie własnych klas reguł URL
|
|
--------------------------------
|
|
|
|
> Note|Uwaga: Używanie własnych klas reguł URL jest wspierane od wersji 1.1.8.
|
|
|
|
Domyślnie, każda reguła URL zadeklarowana w [CUrlManager] jest reprezentowana jako
|
|
obiekt [CUrlRule], który wykonuje zadanie przetwarzania żądań i tworzenia URLi
|
|
w oparciu o określone reguły. Chociaż klasa [CUrlRule] jest dostatecznie elastyczna aby
|
|
poradzić sobie z wszystkimi formatani URL, czasami wciąż chcemy ją rozszerzyć o dodatkowe
|
|
funkcjonalności.
|
|
|
|
Na przykład, na stronie dilera samochodów, chcemy wspierać format URL w postaci
|
|
`/Manufacturer/Model`, gdzie producent `Manufacturer` i model samochodu `Model`
|
|
muszą zgadzać się z danymi znajdującymi się w bazie danych.
|
|
Klasa [CUrlRule] nie zadziała, gdyż działa w oparciu o statycznie zadeklarowane wyrażenia
|
|
regularne, które nie mają wiedzy o bazie danych.
|
|
|
|
Możemy utworzyć nową klasę reguł URL poprzez rozszerzenie [CBaseUrlRule] i użycie jej
|
|
w jednej lub wielu regułach URL. Używając powyższej strony dilera samochodowego jako przykładu,
|
|
możemy zadeklarować następujące reguły URL:
|
|
|
|
~~~
|
|
[php]
|
|
array(
|
|
// standardowa reguła mapująca '/' do akcji 'site/index'
|
|
'' => 'site/index',
|
|
|
|
// standardowa reguła mapująca '/login' do 'site/login', i tak dalej...
|
|
'<action:(login|logout|about)>' => 'site/<action>',
|
|
|
|
// własna reguła obsługującca format '/Manufacturer/Model'
|
|
array(
|
|
'class' => 'application.components.CarUrlRule',
|
|
'connectionID' => 'db',
|
|
),
|
|
|
|
// standardowa reguła obsługująca 'post/update', i tak dalej...
|
|
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
|
|
),
|
|
~~~
|
|
|
|
W powyższym kodzie użyliśmy własnej klasy reguł URL `CarUrlRule` aby obsłużyć format URL
|
|
`/Manufacturer/Model`. Klasa ta może zostać napisana w następujący sposób:
|
|
|
|
~~~
|
|
[php]
|
|
class CarUrlRule extends CBaseUrlRule
|
|
{
|
|
public $connectionID = 'db';
|
|
|
|
public function createUrl($manager,$route,$params,$ampersand)
|
|
{
|
|
if ($route==='car/index')
|
|
{
|
|
if (isset($params['manufacturer'], $params['model']))
|
|
return $params['manufacturer'] . '/' . $params['model'];
|
|
else if (isset($params['manufacturer']))
|
|
return $params['manufacturer'];
|
|
}
|
|
return false; // this rule does not apply
|
|
}
|
|
|
|
public function parseUrl($manager,$request,$pathInfo,$rawPathInfo)
|
|
{
|
|
if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches))
|
|
{
|
|
// sprawdź $matches[1] oraz $matches[3] aby zobaczyć, czy
|
|
// zawierają one producenta oraz model z bazy danych
|
|
// Jeśli tak, to ustaw $_GET['manufacturer'] oraz $_GET['model']
|
|
// i zwróć 'car/index'
|
|
}
|
|
return false; // reguła ta nie ma zastosowania
|
|
}
|
|
}
|
|
~~~
|
|
|
|
Własna klasa URL musi implementować dwie abstrakcyjne metody zadeklarowane w klasie [CBaseUrlRule]:
|
|
|
|
* [createUrl()|CBaseUrlRule::createUrl()]
|
|
* [parseUrl()|CBaseUrlRule::parseUrl()]
|
|
|
|
Poza powyższym, typowym użyciem, własne klasy reguł URL mogą być implementowane z innych powodów.
|
|
Na przykład, chcemy napisać klasę reguł logującą parsowanie URL i tworzenie żądania.
|
|
Może być to bardzo użyteczne na etapie rozwoju aplikacji. Możemy również napisać klasę reguły
|
|
do wyświetlania specjalnej strony błędu 404 w przypadku gdy wszystkie pozostałe reguły URL
|
|
nie będą potrafiły rozszyfrować aktualnego żądania. Zauwać, że w takim przypadku, reguła
|
|
z tą specjalną klasą musi zostać zadeklarowana jako ostatnia.
|
|
|
|
<div class="revision">$Id: topics.url.txt 3591 2012-02-17 21:44:32Z qiang.xue@gmail.com $</div> |