O tym, jak dużą rolę odgrywają adresy URL, może świadczyć choćby jedna z porad zawartych na witrynie konsorcjum WWW: „Dobre adresy URL się nie zmieniają”. Jak zatem dokonywać modyfikacji witryny WWW, aby zmiany implementacji nie dezaktualizowały adresów URL? Jak zamienić mało atrakcyjne adresy index.php?id=666 na statyczne index_666.html? Rozwiązaniem problemu są przyjazne adresy URL, których zastosowanie wyjaśnię na podstawie czterech przykładów.
W sieci WWW zasoby są identyfikowane adresami URL (ang. Universal Resource Locators). W przypadku statycznych stron WWW adresy takie kończą się zazwyczaj nazwą pliku, na przykład opis.html. Natomiast dynamiczne
strony generowane w PHP bardzo często zawierają zmienne
index.php?menu=artykuly&id=123&jezyk=pl
Fragment adresu, występujący po znaku zapytania,
definiuje zmienne, jakie będą przekazane do skryptu metodą GET protokołu HTTP. W dokumentach
XHTML separator & powinien być zapisywany w postaci encji {stala}&{/stala}:
index.php?menu=artykuly&id=123&jezyk=pl
Adresy, które zawierają zmienne, mają kilka wad. Po pierwsze, są długie i przez to trudne do zapamiętania czy choćby przepisania. Po drugie, nie zawierają w zasadzie żadnych informacji na temat udostępnianych zasobów. Adres janko-muzykant.html zawiera tytuł noweli, podczas gdy użycie PHP i identyfikatora utworu w bazie dany chtekst.php?id=123 wygląda tajemniczo.
Między innymi z tego powodu adresy ze zmiennymi są gorzej traktowane przez wyszukiwarki. Wreszcie po trzecie, w przypadku reorganizacji silnika witryny często zmianie ulegają adresy URL. Jest to oczywiście bardzo niekorzystne.
Przygotowując witrynę WWW, należy zadbać o to, aby późniejsze aktualizacje strony zachowywały
dotychczasowy zestaw adresów URL.
Przykłady praktyczne
Praktyczne zastosowanie przyjaznych adresów URL omówię na przykładzie czterech witryn. Pierwsza z nich prezentuje nuty oraz teksty kolęd i jest przygotowana w oparciu o pliki tekstowe. Druga zawiera bibliografię książek na temat webmasteringu i wykorzystuje bazę danych. Trzecia jest katalogiem płyt i utworów zespołów rockowych, zaś czwarta prezentuje dane pochodzące z pliku log serwera Apache.
Witryna \”Śpiewnik kolęd\”
Witryna \”Śpiewnik kolęd\” jest dostępna pod adresem http://www.gajdaw.pl/koledy/.
Witryna ta zawiera dwa rodzaje stron: strony wyświetlające opcje menu oraz strony wyświetlające
poszczególne kolędy. Witryna jest wykonana
w PHP, wszystkie dane są przechowywane w plikach tekstowych. Wyboru strony dokonujemy na podstawie dwóch zmiennych dołączanych do adresów URL: id1 oraz id2.
Zmienna id1 identyfikuje wybór rodzaju podstrony.
Wartość 1 oznacza wybór strony z menu, zaś wartość 2 – wybór tekstu kolędy. Druga zmienna,
o nazwie id2, identyfikuje wybraną pozycję menu lub wybraną kolędę.
Na przykład adresy:
index.php?id1=1&id2=1
index.php?id1=1&id2=2
index.php?id1=1&id2=3
wskazują trzy pierwsze opcje menu. Identyfikatorid1 przyjmuje wartość 1, zaś identyfikatorid2 wskazuje wybraną opcję menu: \”Strona główna\” (opcja o identyfikatorzeid2=1), \”Nowości\” (id2=2), \”Kolędy\” (id2=3).
Natomiast adresy:
index.php?id1=2&id2=4
index.php?id1=2&id2=5
identyfikują kolędy. Tym razem identyfikator id1 est równy 2, zaś identyfikator id2 identyfikuje wybraną kolędę: \”Cicha noc\” (kolęda o identyfikatorzeid2=4) oraz \”Do szopy\” (id2=5).
Wszystkie adresy URL odnoszące się do witryny \”Śpiewnik kolęd\” mają postać:
index.php?id1=XXX&id2=YYY
gdzie XXX oraz YYY są liczbami całkowitymi. Rozwiązanie takie posiada wszystkie wymienione wady:
- adresy URL są trudne do zapamiętania;
-
żaden adres URL nie zawiera informacji o udostępnianych
informacjach (w oczach wyszukiwarek
adres cicha-noc.html jest lepiej punktowany od adresu index.php?id1=2&id2=4); -
modyfikacja skryptu (dokładniej: zmiana nazw zmiennych id1 oraz id2) zdezaktualizuje wszystkie
adresy URL.
Witryna \”Bibliografia\”
Witryna pt. \”Bibliografia\”składa się z dwóch rodzajów stron. Pierwszym z nich są strony prezentujące
listę tytułów książek, drugim – strony przedstawiające
szczegółowe informacje o wybranej książce. Na witrynie tej obowiązują dwa rodzaje adresów:
index.php?id1=2&id2=xxx
oraz
index.php?id1=3&id2=yyy
Pod adresami index.php?id1=2&id2=xxx dostępne są zestawienia książek wybranego autora (xxx jest identyfikatorem osoby w bazie danych).Na przykład lista książek napisanych przez Michaela
J. Hernandeza ma adres:
index.php?id1=2&id2=26
ponieważ identyfikatorem M.J.Hernandezawbazie
danych jest liczba 26. Zaś lista książek Chucka White\’a ma adres (identyfikatorem ChuckaWhite\’a jest liczba 8):
index.php?id1=2&id2=8
Drugi rodzaj stron to strony prezentujące szczegółowe
informacje na temat konkretnej książki. W adresach tych stron zmienna id1 przyjmuje wartość 3, zaś zmienna id2 jest identyfikatorem książki w bazie danych. Pod adresem:
index.php?id1=3&id2=6
znajdują się szczegółowe dane książki pt. \”Czytanie kodu\” (identyfikator książki w bazie danych:6). Natomiast informacje o książce \”CSS według Erica Meyer\” (identyfikator2) są dostępne na stronie:
index.php?id1=3&id2=2
Katalog płyt i nagrań: 33 i 1/3
Trzeci przykład, katalog płyt i nagrań zatytułowany 33 i 1/3, jest znacznie bardziej złożony, głównie z powodu liczby podstron oraz danych zawartych w bazie.
Witryna ta udostępnia:
- stronę powitalną (adres index.php?id=2),
-
zestawienie wszystkich:
- wykonawców (adres index.php?id=3),
- płyt (adres index.php?id=4),
- utworów (adres index.php?id=5),
- roczników (adres index.php?id=6),
-
szczegółowe zestawienie:
-
płyt wykonawcy (adres index.php?id=7&
id2=xxx), -
utworów wykonawcy (adres index.php?id=
11&id2=xxx), -
utworów z płyty (adres index.php?id=8&
id2=xxx), -
tekst utworu (adres index.php?id=9&id2=
xxx), - płyt z wybranego rocznika (adres index.php?id=10&id2=xxx).
-
płyt wykonawcy (adres index.php?id=7&
We wszystkich przypadkach zestawień szczegółowych
zmienna id2 zawarta w adresie URL pełni rolę identyfikatora. Identyfikatorem zespołu Led Zeppelin w bazie danych jest liczba 17. Zatem wszystkie płyty Led Zeppelin znajdują się pod adresem:
index.php?id=7&id2=17
Wszystkie piosenki Led Zeppelin znajdziemy na stronie:
index.php?id=11&id2=17
Płyta zespołu Led Zeppelin zatytułowana Houses of the Holy ma identyfikator113.Szczegółowe
informacje na jej temat (tj. listę piosenek, rok wydania, czas trwania) znajdziemy pod adresem:
index.php?id=8&id2=113
Druga z piosenek płyty jest zatytułowana The Rain Song. Ma ona identyfikatorwbaziedanych1005, więc jej tekst znajduje się na stronie:
index.php?id=9&id2=1005
Ostatni rodzaj strony przedstawia płyty z wybranego rocznika. Płyta Houses of the Holy pochodzi z roku 1973. Rocznik ten ma identyfikator11. Lista płyt z roku 1973 (w tym Houses of the Holy) ma adres:
index.php?id=10&id2=11
Analiza pliku log serwera Apache
Czwarty przykład prezentuje w postaci stron WWW zawartość pliku log serwera Apache. Zadaniem aplikacji jest ułatwienie wyszukiwania wszystkich zapytań o zadanej właściwości (np. wszystkich zapytań dotyczących pliku {stala}style.css{/stala}, wszystkich zapytań, jakie nadeszły z hosta {stala}host.example.net{/stala}, itd.)
Zmienna id1 wskazuje rodzaj wybranej strony. Dostępne są trzy rodzaje stron:
Pierwszym są strony zawierające pełne zestawienia:
id1=3 – wszystkie zapytania
id1=4 – wszystkie hosty
id1=5 – wszystkie URL-e
id1=6 – wszystkie przeglądarki (user agent)
id1=7 – wszystkie adresy odsyłające (referer)
id1=8 – wszystkie metody HTTP
id1=9 – wszystkie odpowiedzi HTTP
id1=10 – wszystkie rozszerzenia plików
Drugi rodzaj to strona przedstawiająca szczegóły
wybranego zapytania:
-
id1=11 – szczegóły zapytania
Trzecim rodzajem są strony zawierające zapytania
HTTP odfiltrowane jednym z kryteriów:
-
id1=12 – zapytania z wybranego hosta
id1=13 – zapytania o wybrany adres URL
id1=14 – zapytania z wybranej przeglądarki
id1=15 – zapytania o zadanej wartości referer
id1=16 – zapytania o zadanej metodzie HTTP
id1=17 – zapytania o zadanej odpowiedzi HTTP
id1=18 – zapytania dotyczące plików o zadanym rozszerzeniu
Na witrynie tej – z racji na ilość danych – jest zastosowane
stronicowanie wyników. Rolę wskaźnika wybranej strony odgrywa zmienna id2 lub id3.
Pełne zestawienie adresów URL oraz podstron witryny zawiera tabela 1.
Oto cztery przykładowe adresy.
Zarządzanie
przestrzenią adresów URL
Przed przekształceniem adresów URL do bardziej czytelnej postaci należy odpowiedzieć na pytanie: pod jakimi adresami URL witryna i jej wszystkie podstrony powinny być widoczne w internecie?
Adresy URL witryny pt. \”Kolędy\”
W przypadku witryny \”Śpiewnik kolęd\” wybrałem adresy odpowiadające nazwom opcji menu głównego oraz tytułom kolęd. W miejsce opisanych powyżej opcji menu głównego:
index.php?id1=1&id2=1
index.php?id1=1&id2=2
index.php?id1=1&id2=3
...
stosuję adresy:
index.html
nowosci.html
koledy.html
...
W miejsce adresów kolęd:
index.php?id1=2&id2=4
index.php?id1=2&id2=5
...
wykorzystuję przekształcone nieco tytuły kolęd:
cicha-noc.html
do-szopy.html
...
Podsumowując, witryna \”Śpiewnik kolęd\” stosuje trzy rodzaje adresów URL:
- index.html – adres strony głównej (pierwotnie: index.php?id1=1&id2=1);
- adresy kolejnych opcji menu (tytuły opcji pozbawione polskich znaków, przekształcone do małych liter), np. koledy.html, adresy.html, itd.;
-
adresy kolęd: tytuły kolęd przekształcone tak jak nazwy opcji (dodatkowo: spacje zastępujemy
myślnikiem), np. do-szopy.html, cicha-noc.html, itd.
Adresy witryny pt. \”Bibliografia\”
Na witrynie \”Bibliografia\”adresy odpowiadają tytułom książek oraz danym autorów. W miejsce adresu:
index.php?id1=2&id2=1
stosuję adres:
meyer_eric_a.html
Natomiast zamiast adresu:
index.php?id1=3&id2=7
pojawi się adres:
sql_dla_kazdego.html
Ogólnie, adres strony powstaje przez przekształcenie
imienia i nazwiska autora lub tytułu książki:
101_praktycznych_skryptow_na_strone_www.html
bazy_danych_dla_zwyklych_smiertelnikow.html
css_wedlug_erica_meyera_kolejna_odslona.html
html_xhtml_i_css_biblia.html
...
hernandez_michael_j.html
meyer_eric_a.html
schlossnagle_george.html
...
Adresy witryny pt. \”33 i 1/3\”
Adresy stosowane na witrynie 33 i 1/3 są zawarte
w tabeli 1. W miejsce opcji menu głównego stosujemy krótkie, jednoczłonowe nazwy plików:
index.php
wykonawcy.php
plyty.php
...
Natomiast strony posiadające identyfikatory zostają podzielone na kategorie.
Płyty otrzymują przedrostek p_:
p_abbey_road.html
p_the_unforgettable_fire.html
p_day_at_the_races.html
...
Utwory adresujemy z prefiksem u_:
u_one.html
u_mamma_mia.html
u_every_breath_you_take.html
...
Roczniki poprzedzamy przedrostkiem r_:
r_1971.html
r_1972.html
r_1973.html
...
Lista wszystkich utworów wykonawcy otrzymuje
przedrostek w_ i przyrostek _u:
w_jethro_tull_u.html
w_van_halen_u.html
w_zucherro_u.html
...
Zaś lista płyt wykonawcy: przedrostek w_ oraz przyrostek _p:
w_abba_p.html
w_the_beatles_p.html
w_jimi_hendrix_p.html
...
Adresy witryny log
Adresy witryny log są najbardziej skomplikowane.
Głównie z powodu zastosowania stronicowania
wyników. Kolejne strony wyników otrzymują przyrostki -p2 (strona druga), -p3 (strona trzecia) itd. Na przykład kolejne strony przedstawiające wszystkie żądania mają adresy:
request.html - strona pierwsza
request-p2.html - strona druga
request-p3.html - strona trzecia
request-p4.html - strona czwarta
Dodatkowo, w odróżnieniu od witryn Bibliografiaoraz33i1/
3,adresy powstają w oparciu o identyfikatory rekordów. Adresstronyprezentującej
żądania dotyczące adresu artykuly.html ma postać
url-11.html
gdyż adres artykuly.html ma identyfikator11w bazie danych.
Przeglądarka Mozilla/4.0 ma identyfikator w bazie danych 3. Zatem trzecia strona żądań, jakie
nadeszły z przeglądarki Mozilla/4.0, ma adres:
ua-3-p3.html
Translacja adresów
Adresy URL należy poddać dwukierunkowej translacji. Zapytania HTTP nadchodzące z przeglądarek
do serwera WWW będą się odwoływały do nieistniejących plików .html. Ponieważ pliki takie nie istnieją, żądania muszą być przekierowane do adresów .php ze zdefiniowanym i odpowiednimi zmiennymi. Żądanie:
GET /cicha-noc.html HTTP/1.1
musi zostać skierowane pod adres:
index.php?id1=2&id2=4
Przekształcaniem nadchodzących zapytań HTTP zajmuje się moduł mod_rewrite serwera Apache.
W drugim kierunku translacja polega na przekształceniu adresów .php na adresy .html. W kodzie HTML wysyłanych stron WWW nie mogą pojawić się adresy index.php?id1=2& id2=4. Adres taki należy przekształcić do postaci cicha-noc.html.
Translację wykonuje skrypt index.php odpowiedzialny za wysyłanie kodu HTML do przeglądarek.
Zamiast hiperłącza:
Cicha noc
w kodzie HTML wysyłanej strony umieszczam odnośnik:
Cicha noc
Adresy podane w powyższym przykładzie pochodzą z przykładu Kolędy. Identyczny mechanizm
jest wykorzystany we wszystkich czterech przykładach.
{stala}mod_rewrite:{/stala} translacja adresów zawartych w przychodzących zapytaniach HTTP
W celu zamiany adresów URL zawartych w zapytaniach
HTTP korzystamy z modułu {stala}mod_rewrite.{/stala}
W pliku konfiguracyjnym {stala}.htaccess {/stala}serwera
Apache umieściłem dyrektywę włączającą przepisywanie adresów URL oraz dodatkowo zablokowałem listowanie zawartości katalogu i ustaliłem nazwę domyślnej strony WWW zawartej w folderze:
RewriteEngine on
Options -Indexes
DirectoryIndex index.php
Następnie wymieniłem kolejno reguły translacji adresów URL. Oto translacje, jakie należy wykonać w przypadku witryny \”Kolędy\”. Najpierw opcje menu:
RewriteRule index.html index.php?id1=1&id2=1
RewriteRule nowosci.html index.php?id1=1&id2=2
RewriteRule koledy.html index.php?id1=1&id2=3
RewriteRule akordy.html index.php?id1=1&id2=4
...
po czym reguły dotyczące poszczególnych kolęd:
RewriteRule a-wczora-z-wieczora.html
index.php?id1=2&id2=0
RewriteRule ach-ubogi-zlobie.html index.php?id1=2&id2=1
RewriteRule aniol-pasterzom-mowil.html index.php?id1=2&id2=2
...
Zwróć uwagę, że separatorem zmiennych jest znak &. W pliku {stala}.htaccess{/stala} nie możesz stosować jako separatora encji {stala}&.{/stala}
Na koniec dodałem jeszcze reguły translacji adresów
URL dokumentów z danymi (w przykładzie \”Kolędy\” witryna udostępnia pliki PDF, MUS, TXT oraz PNG). Ponieważ kolejne dokumenty różnią się wyłącznie rozszerzeniami, wykorzystałem wyrażenia
regularne i przechwytywanie fragmentów:
RewriteRule ^cicha-noc.(png|pdf|txt|mus)$ dane/koledy/cicha-noc.
RewriteRule ^do-szopy.(png|pdf|txt|mus)$ dane/koledy/do-szopy.
...
Po umieszczeniu pliku {stala}.htaccess{/stala} o podanej zawartości w tym samym folderze, w którym znajduje się plik index.php, serwer Apache będzie udostępniał pliki .html. Działanie serwera Apache jest w pełni przezroczyste dla przeglądarki. Z punktu widzenia przeglądarki, wszystko będzie wyglądało tak, jak gdyby na serwerze fizycznie były umieszczone pliki .html o podanych nazwach.
Proces przekierowywania przez moduł {stala}mod_rewrite{/stala} jest również przezroczysty dla skryptów
PHP. Z punktu widzenia skryptu PHP wszystko wygląda tak, jak gdyby użytkownik zażądał bezpośrednio
pliku .php, a nie .html.
Oczywiście plik {stala}.htaccess{/stala} należy przygotować do każdego przykładu z osobna.
Translacja hiperłączy
zawartych w kodzie HTML
Adresy hiperłączy, jakie występują w dokumentach
HTML, poddałem ręcznej konwersji. Przygotowałem
plik tekstowy definiujący przekształcenia. Plik ten we wszystkich przykładach nazywa się {stala}filtr.log.{/stala} Na witrynie z kolędami ma on postać:
\"index.php?id1=1&id2=1\"
\"index.html\"
\"index.php?id1=1&id2=2\"
\"nowosci.html\"
\"index.php?id1=1&id2=3\"
\"koledy.html\"
\"index.php?id1=2&id2=0\"
\"a-wczora-z-wieczora.html\"
\"index.php?id1=2&id2=1\"
\"ach-ubogi-zlobie.html\"
Pierwszy napis jest napisem zamienianym, a drugi
– napisem, na jaki zamieniamy. Separatorem jest znak tabulacji (w PHP zapisywany jako \”\\t\”).
Z powyższych linijek wynika między innymi, że w produkowanym kodzie HTML w miejsce napisu \”index.php?id1=1&id2=1\” należy wstawić napis \”index.html\” (Zwróć uwagę na cudzysłowy! Pozwalają one uniknąć dwuznaczności!).
W którym miejscu dokonać konwersji? Oczywiście
po przetworzeniu całego skryptu, tuż przed wysłaniem wynikowego kodu HTML do klienta.
Jeśli strona jest wykonana z wykorzystaniem szablonów
Smarty, to przetworzony skrypt możemy uzyskać, wywołując metodę{stala} fetch():{/stala}
$strona = $s->fetch(\'uklad.tpl\');
Zmienna $strona zawiera teraz kod HTML wygenerowanej
strony (po przetworzeniu szablonu). Następnie należy przygotować tablicę podmian. Po wczytaniu pliku {stala}filtr.log{/stala} i usunięciu z niego komentarzy przekształcam go w dwuwymiarową tablicę o nazwie $filtr:
$tmpFiltr = file_get_contents(\'filtr.log\');
$tmpFiltr= uncomment_and_trim($tmpFiltr);
list($w, $k, $filtr)=string2VArray($tmpFiltr, \"\t\");
Gdy strona i tablica podmian są gotowe (zmienne $strona oraz $filtr), dokonuję translacji adresów:
$strona = str_replace($filtr[0],$filtr[1], $strona);
po czym otrzymany dokument wysyłamy do przeglądarki:
echo $strona;
Podsumowując, przekształcenie kodu HTML wysyłanej strony wykonujemy przy użyciu
- metody {stala}fetch(){/stala} klasy Smarty;
-
funkcji {stala}file_get_contents(){/stala}, {stala}uncomment_
and_trim(){/stala}, {stala}string2VArray(){/stala},
{stala}str_replace();{/stala} - instrukcji echo.
Automatyczne generowanie plików .htaccess oraz filtr.log
Generowanie plików translacji
na podstawie plików tekstowych
Całym procesem translacji sterują dwa pliki tekstowe: {stala}.htaccess{/stala} oraz {stala}filtr.log.{/stala} Jak widziałeś,struktura obu tych plików jest dość oczywista i wynika
z danych zawartych w serwisie: w jednej linii występują obok siebie adresy .html oraz .php:
.htaccess
RewriteRule ach-ubogi-zlobie.html index.php?id1=2&id2=1
filtr.log
\"index.php?id1=2&id2=1\"
\"ach-ubogi-zlobie.html\"
W celu usprawnienia aktualizacji witryny warto przygotować skrypt, który automatycznie wygeneruje
oba pliki.
W przypadku witryny \”Kolędy\” mamy do czynienia z plikami tekstowymi. Menu witryny powstaje na podstawie pliku 00strony.log. W pliku tym w każdej linijce jest wymieniona jedna opcja menu:
Strona główna|index|1
Nowości|nowosci|1
Kolędy|koledy|1
...
Natomiast kolędy są opisane w pliku 00lista.log:
Bóg się rodzi|bog-sie-rodzi|1
Cicha noc|cicha-noc|1
Do szopy|do-szopy|1
...
Tworzenie plików {stala}.htaccess{/stala} oraz {stala} filtr.log{/stala} wymaga
jedynie odpowiedniego przetworzenia obu podanych plików.
Oba pliki tekstowe odczytuję i przekształcam w dwuwymiarowe tablice (zmienne $koledy oraz $menu), zapamiętując liczbę wierszy każdego z nich (zmienne $koledy_c i $menu_c):
//kolędy
$plk = file_get_contents(\'00koledy.log\');
list($koledy_c, $koledy) = string2HArray($
plk);
//menu
$plk = file_get_contents(\'00menu.log\');
list($menu_c, $menu) = string2HArray($
plk);
Translacje adresów dotyczących menu zawarte w pliku .htaccess produkuje następująca pętla for przedstawiona na listingu 1.
for ($i = 0; $i < $menu_c; $i++) {
$tmp .= \'RewriteRule \' .
str_pad($menu[$i][1] . \'.html\', 15, \' \') . \'index.php?id1=1&id2=\';
$tmp .= $i + 1;
$tmp .= \"\n\";
}
W podobny sposób generuję pozostałe wpisy pliku {stala}.htaccess{/stala} oraz plik {stala}filtr.log.{/stala}
Po uruchomieniu skryptu generuj-translacje.php w folderze cfg/ zostaną utworzone pliki {stala}.htaccess{/stala} oraz {stala}filtr.log.{/stala} Plik {stala}.htacces{/stala} należy przekopiować do folderu, w którym znajduje się plik index.php. Natomiast plik filtr.log-wfolderzedane/filtr/.
Generowanie plików translacji
na podstawie bazy danych
Przykłady \"Bibliografia\",\"33i1/3\"oraz\"Log\"różnią się od \"Śpiewnika kolęd\" dwoma cechami:
- dane są przechowywane w bazie danych
- do generowania plików {stala}.htaccess{/stala} oraz {stala}filtr.log{/stala} wykorzystany jest szablon Smarty.
Zawartość pliku {stala}.htaccess{/stala}, jaki należy wygenerować dla witryny \"Bibliografia\",rozpoczyna się od wpisów:
RewriteRule 101_praktycznych_skryptow_na_strone_www.html index.php?id1=3&id2=8
RewriteRule bazy_danych_dla_zwyklych_smiertelnikow.html index.php?id1=3&id2=10
RewriteRule css_wedlug_erica_meyera_kolejna_odslona.html index.php?id1=3&id2=1
...
Odpowiadające im wpisy pliku {stala}filtr.log{/stala} są następujące:
\"index.php?id1=3&id2=8\" \"101_praktycznych_skryptow_na_strone_www.html\"
\"index.php?id1=3&id2=10\" \"bazy_danych_dla_zwyklych_smiertelnikow.html\"
\"index.php?id1=3&id2=1\" \"css_wedlug_erica_meyera_kolejna_odslona.html\"
...
$db = new DataBaseAccess();
$s = new Smarty();
$tabKsiazek = array();
$ksiazki = $db->DBA_listaWszystkichIDKsiazek();
foreach ($ksiazki as $ksiazka) {
$tmp = new Ksiazka($db);
if ($tmp->getPropertiesFromDB($ksiazka)) {
$nazwa_pliku = string2filename($tmp->Ftytul);
$tabKsiazek[$ksiazka] = $nazwa_pliku;
}
}
$s->assign(\'ksiazki\', $tabKsiazek);
...
$s1 = $s->fetch(\'htaccess.tpl\');
file_put_contents(\'filtr/.htaccess\',$s1);
$s2 = $s->fetch(\'substitutions-log.tpl\');
file_put_contents(\'filtr/substitutions.log\', $s2);
Listing 2 przedstawia szkielet skryptu generuj-translacje.php, którego zadaniem jest wygenerowanie plików {stala}.htaccess{/stala} oraz {stala}filtr.log{/stala}. Po pobraniu listy wszystkich książek z bazy (wywołanie DBA_lista Wszystkich ID Ksiazek()) w pętli foreach przygotowujemy informacje o kolejnej książce. Nowy adres książki powstaje po przekształceniu tytułu książki funkcją {stala}string2filename():{/stala}
$nazwa_pliku = string2filename($tmp->Ftytul);
Funkcja {stala}string2filename(){/stala} zmienia wielkość liter i usuwa niedozwolone znaki. Na przykład wywołanie:
$nazwa_pliku = string2filename(\'HTML, XHTML i CSS. Biblia\');
zwróci tytuł:
html_xhtml_i_css_biblia
Dane dotyczące książek są w szablonie przetwarzane
instrukcją foreach:
{foreach key=k item=v from=$ksiazki}
RewriteRule {$v}.html index.php?id1=3&id2={$k}
{/foreach}
Niewątpliwą zaletą wykorzystania szablonów Smarty do generowania plików {stala}.htaccess{/stala} oraz {stala}filtr.log{/stala} jest fakt, że pliki te powstają na podstawie
identycznych danych, a różnią się wyłącznie szablonem.
Uaktualnianie witryny
Witrynę wykorzystującą opisane translacje adresów URL aktualizuję następująco:
Jak widzisz, jest to proces w pełni zautomatyzowany,
wymagający jedynie uruchomienia jednego skryptu i przekopiowania dwóch plików. Dodam, że skrypt generuj-translacje.php jest skryptem administracyjnym przeznaczonym wyłącznie dla administratora witryny (skrypt ten nie powinien być dostępny publicznie).
Przygotowywanie witryny offline
Jedną z korzyści stosowania przyjaznych adresów
URL jest łatwość generowania witryn offline. Witryna taka może być nagrana na płytę CD.
Oczywiście witrynę offline możesz przygotować,
korzystając z odpowiedniego oprogramowania,
na przykład HTTrack czy Teleport. Jednakże programy te muszą ingerować w kod HTML. Niejednokrotnie zdarza im się zamienić poprawny kod HTML na kod zawierający błędy.
Przygotowując przykłady towarzyszące moim artykułom i przeznaczone na płytę CD, stosuję zawsze bezpieczne adresy URL. Mam wtedy pełną kontrolę nad generowanym kodem HTML. Gwarantuje mi to, że przygotowany kod jest dokładnie taki, jak to zaplanowałem.
Do zgrania witryny stosującej bezpieczne adresy URL wystarczy program wget. Program ten, początkowo przygotowany dla systemów u*ix, jest dostępny także na platformę Windows.
Polecenie:
wget -r -l 10000 http://localhost/3313/index.html
Parametr -l ustala głębokość rekurencji. Podając dużą liczbę masz gwarancję, że wget dotrze do wszystkich plików witryny.
Zalety
W witrynie stosującej dwukierunkową translację
adresów URL uniezależniamy adresy URL od implementacji. Wprowadzamy do aplikacji kolejną warstwę oprogramowania, dzięki czemu zarządzanie
adresami URL odbywa się poza silnikiem witryny
i jest od niego niezależne. Kod witryny mogę dowolnie modyfikować(włączając w to zmienne URL). Muszę jedynie pamiętać o dostarczeniu odpowiednich danych dotyczących translacji (czyli dwóch plików tekstowych: {stala}.htaccess{/stala} oraz {stala}filtr.log{/stala}).Administracją adresów URL może zajmować się osobny zespół odpowiedzialny za pozycjonowanie i wizerunek firmy w internecie.
Oczywiście cała witryna jest wykonana w PHP i jest ona w pełni dynamiczna.
Wady
Głównym problemem jest oczywiście wydajność
takiego rozwiązania. Tutaj należy pamiętać, że działanie modułu {stala}mod_rewrite{/stala} jest o wiele bardziej wydajne, gdy reguły przeniesiemy z pliku {stala}.htaccess{/stala} dotyczącego konkretnego folderu do ogólnego pliku konfiguracyjne gohttpd.conf.
Drugim sposobem przyspieszenia działania witryny jest jej podział na mniejsze fragmenty. Poszczególne działy można umieścić w osobnych folderach. W każdym folderze będą wykonywane wyłącznie translacje dotyczące danego działu.
Jeśli i to okaże się niewystarczające, można jeszcze udostępnić witrynę statyczną, wygenerowaną
na podstawie skryptów. Aktualizujemy witrynę,
zgrywamy ją programem do tworzenia kopii witryn (np. wget), po czym na serwerze umieszczamy
wersję statyczną. Takie rozwiązanie będzie na pewno bardzo wydajne, jednakże pozbawione interaktywności.
Przydatne funkcje
file_get_contents()
{stala}file_get_contents(){/stala} jest funkcją standardową PHP,która odczytuje zawartość całego pliku o podanej nazwie. Po wykonaniu instrukcji:
$p = file_get_contents(\'dane.txt\');
zmienna {stala}$p{/stala} będzie zawierała całą zawartość pliku dane.txt bez żadnych modyfikacji. Funkcjata jest binarnie bezpieczna.
uncomment_and_trim()
Funkcja {stala}uncomment_and_trim(){/stala} jest zawarta w pliku {stala}comment.inc.php{/stala}. Odpowiada ona za usunięcie komentarzy w stylu u*ixowego shella (od znaku # do końca linii) oraz pustych linii. Dzięki temu plik {stala}substitutions.log{/stala} może zawierać puste linie oraz komentarze.
string2VArray()
Funkcja {stala}string2VArray(){/stala} jest zawarta w pliku {stala}vharray.inc.php{/stala}. Służy ona do odczytywania zawartości
z plików przechowujących tabelę danych. Powoduje ona przekształcenie odczytanego pliku w dwuwymiarową tablicę.
Jeśli dany jest plik dane.txt o zawartości:
Jan|Czerwony|32
Piotr|Zielony|44
Anna|Niebieska|17
Krystyna|Czarna|23
to po wywołaniu:
$p = file_get_contents(\'dane.txt\');
list($wiersze, $kolumny, $dane) = string2VArray($p);
w zmiennej {stala}$wiersze{/stala} będzie przechowywana liczba rekordów (w powyższym przykładzie: 4), zmienna {stala}$kolumny{/stala} będzie zawierała liczbę kolumn
(w przykładzie: 3), zaś tabela {stala}$dane{/stala} będzie zawierała kolejne rekordy i ich pola:
$dane[0][0] === Jan
$dane[0][1] === Piotr
$dane[0][2] === Anna
$dane[0][3] === Krystyna
$dane[1][0] === Czerwony
$dane[1][1] === Zielony
$dane[1][2] === Niebieska
$dane[1][3] === Czarna
$dane[2][0] === 32
$dane[2][1] === 44
$dane[2][2] === 17
$dane[2][3] === 23
Funkcja zwraca w wyniku tablicę, której pierwszym
elementem jest liczba rekordów odczytanych
z pliku, drugim - liczba pól, zaś trzecim - dwuwymiarowa tablica zawierająca dane.
Funkcja zakłada poprawność pliku z danymi (tj. każdy wiersz powinien zawierać tę samą liczbę pól). Separator pól jest opcjonalnym drugim argumentem funkcji. W celu zmiany separatora | na * należy funkcję wywołać:
list($w, $k, $dane) = string2VArray($p, \'*\');
str_replace()
Funkcja {stala}str_replace(){/stala} jest standardowo dostępna w PHP. Dokonuje ona zamiany napisów w napisie. Funkcję możemy stosować do zamiany pojedynczych napisów oraz tablic.
W prostszej formie wywołanie ma postać:
$nowy = str_replace(\'red\', \'czerwony\', $stary);
Spowoduje ono zastąpienie wszystkich wystąpień napisu \"red\" w zmiennej {stala}$stary {/stala}napisem \"czerwony\".
W drugim wariancie zamieniane napisy oraz ich nowe odpowiedniki przekazujemy do funkcji w tablicach.
Najpierw przygotowujemy tablice:
$stare = array(\'one\', \'white\', \'cat\');
$nowe = array(\'jeden\', \'biały\', \'kot\');
po czym dokonujemy zamiany wszystkich napisów z tablicy {stala}$stare{/stala} na odpowiadające im napisy z tablicy {stala}$nowe{/stala}:
$po = str_replace($stare, $nowe, $przed);
string2filename()
Funkcja {stala}string2filename(){/stala} nie jest standardowo dostępna w PHP. Znajdziesz ją w pliku filenames.inc.php. Dokonuje ona zamiany znaków w napisie
w taki sposób, by otrzymany napis zawierał wyłącznie małe litery, cyfry oraz ewentualnie znaki podkreślenia.
Po wywołaniu:
$n = string2filename(\'ŁukaszŻółwiowski\');
echo $n;
otrzymamy:
lukasz_zolwiowski
Zaś instrukcja:
echo string2filename(\'\"Czy to jesień?\"\');
wydrukuje:
czy_to_jesien
Złośliwy ampersand
W generowanym kodzie HTML stosujemy zamiast znaku & - encję {stala}&{/stala}:
...
Natomiast w pliku .htaccess należy stosować zwykły ampersand, a nie encję:
meyer_eric_a.html index.php?id1=2&id2=1