Dokumentacja Kursy i specyfikacje
mod_rewrite
Korzystanie z wyrażen regularnych
Potęga mod_rewrite'a wiąże się z możliwością tworzenia zaawansowanych wzorców składni. Im bardziej zawiłe przepisanie tym bardziej złożone będzie wyrażenie regularne. Dlatego też, aby w pełni korzystać z możliwości mod_rewrite, musisz opanować wyrażenia regularne. Poniżej znajdziesz kilka przykładów, które bazują na rozwiniętych wyrażeniach.
RewriteEngine On
RewriteRule ^sklep/([0-9][0-9])/$ sklep.php?id=$1
Pierwszy parametr to nasza maska. Mówi ona – sprawdzany ciąg znaków zaczyna się od "sklep/" i po nim występują dwie cyfry, np: "sklep/23/". Okrągłe nawiasy służą do grupowania. Tekst dopasowany w nawiasach może być przekazany jako parametr do docelowego adresu. Czyli w rezultacie działania tej reguły nastąpi przepisanie:
sklep/23/ -> sklep.php?id=23
Parę słów rozwinięcia:
- znaki ^ oraz $ informują o dopasowywaniu od początku do końca tekstu źródłowego. Jeśli je pominiemy, wyrażenie regularne będzie szukać wystąpienia tekstu w dowolnym miejscu tekstu. Przykładowo:
tekst: /produkty/promocja/koszulka/czerwona
maska: ^/promocja/$
wynik: błąd – nie znaleziono szukanej treści. Według naszej maski podany na wejściu tekst powinie zawierać tylko "/promocja/" i nic więcej.
tekst: /produkty/promocja/koszulka/czerwona
maska: /promocja/
wynik: sukces – w szukanym tekście występuje fraza "/promocja/". - [0-9] – znak z podanego zakresu znaków,
- (...) - nawiasy te służą grupowaniu. Wartość wyrażenia dopasowania w nawiasach jest przekazywana jako parametr – można ją wypisać używając $1 do $9
Kolejny przykład:
RewriteEngine On
RewriteRule ^artykul/([a-zA-Z]+)/$ /wyswietl.php?artykul=$1
Jest on bardzo podobny do poprzedniego. Tym razem w masce dopasowania sprawdzamy, czy tekst zaczyna się od frazy "artykul/", po którym spodziewamy się tytułu artykułu. W tym celu użyliśmy grupowania zakresu małych i dużych liter. Znak plusa informuje, że może wystąpić jedna lub wiele liter. Oto przykłady: tekst: /artykul/MalyTytul/
wynik: /wyswietl.php?artykul=MalyTytul tekst: /artykul/123/
wynik: błąd dopasowania (tytuł artykułu nie zawiera liter) Nawiązując do przykładu z pierwszego rozdziału, możemy stworzyć już regułę, która zrealizuje to przepisanie. Przypomnijmy: tekst: http://moja-strona.home.pl/nowosci/3487
oczekiwany wynik: http://moja-strona.home.pl/wyswietl.php?id=3487
RewriteEngine On
RewriteRule ^nowosci/([0-9]+)$ /wyswietl.php?id=$1
Dodawanie kończącego slasha
Patrząc na te przykłady możesz powiedzieć – wszystko dobrze, tylko co w przypadku, kiedy użytkownik wpisze adres bez kończącego go slasha? Mam robić osobne reguły dla każdego przypadku? Nie musisz. Pamiętaj, że po każdym wykonanym przepisaniu strona jest wywoływana ponownie, z nowym URLem. I co się z wiąże, ponownie są przetwarzane reguły mod_rewrite. Rozbudujmy więc ostatni przykład:
RewriteEngine On
RewriteRule ^artykul/([a-zA-Z]+)$ /artykul/$1/ [R]
RewriteRule ^artykul/([a-zA-Z]+)/$ /wyswietl.php?artykul=$1
Co się stanie po wywołaniu adresu "/artykul/DuzyTytul" ?
- Zostanie wykonana pierwsza reguła, która zamieni adres na postać "/artyklul/DuzyTytul/" oraz wykona przekierowanie na tą stronę (o tym mówi flaga R).
- Nowy adres nie zostanie już dopasowany do pierwszej reguły, więc serwer spróbuje go dopasować do kolejnej reguły - co zakończy się sukcesem.
Niepoprawne reguły powodujące zapętlenia są najczęstszym błędem.
Jak ustrzec się przed zapętleniem reguł?
Przede wszystkim należy pamiętać, że po przepisaniu adresu, następuje ponowne wywołanie strony - już z nowym adresem. Wtedy również ponownie zostają wykonane reguły zapisane w pliku .htaccess. Należy więc tak konstruować reguły, aby nie zaszedł przypadek, kiedy raz przepisany adres jest przepisywany ponownie przez tą samą regułę.
RewriteEngine On
RewriteRule (.*) /pokaz.php/$1
Pierwszy przebieg: tekst: artykuly/478
wynik: /pokaz.php/artykuly/478 Drugi przebieg: tekst: /pokaz.php/artykuly/478
wynik: /pokaz.php/pokaz.php/artykul478 Jak widać, reguła ta będzie wykonywać się w nieskończoność. Oto poprawiona wersja, która opiera się na sprawdzeniu, czy przepisywany adres nie zawiera kropki.
RewriteEngine On
RewriteRule ^([^.]*)$ /pokaz.php/$1
Pierwszy przebieg wygląda podobnie jak w poprzednim przykładzie, natomiast drugi zwróci błąd, gdyż przepisywany tekst zawiera już kropkę. Dlaczego wymuszamy przepisanie tekstu który nie zawiera kropki? W normalnym przypadku kropka pojawia się tylko w nazwie pliku - w tym przypadku jest to pokaz.php. Inną metodą jest użycie RewriteCond w celu sprawdzenia, czy adres nie zawiera rzeczywistego katalogu i nazwy pliku - jeśli tak, oznacza to, że posiadamy już adres w ostatecznej postaci.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /pokaz.php/$1
Oba dopasowania RewriteCond sprawdzają zawartość wywołanego adresu - pierwsze sprawdza, czy adres nie prowadzi do pliku (parametr -f), natomiast drugie czy nie jest to katalog (parametr -d). Po pierwszym przebiegu i wykonaniu reguły zmianna REQUEST_FILENAME będzie zawierać już nazwę pliku tj. pokaz.php