NNPlaya.pl

Ostatnie prace

mod_rewrite, a ścieżki do plików

PHP

Któż nie chciałby mieć linków na swojej stronie w ich bardziej przyjaznej formie, bez żadnych znaków "?", "=" czy "&"? Na szczęście Apache zapewnia nam wsparcie dla tego typu rozwiązań, dając nam do ręki możliwość skorzystania z pliku .htaccess i zdefiniowania w nim reguł przepisywania linków. O tym jak to zrobić napisano już wiele artykułów i książek. W tej notce powiem, co zrobić z problemem ścieżek do plików na stronie.

W czym problem?

Jeśli wywołujemy w przeglądarce stronę http://mojadomena.pl/, a w odpowiedzi dostajemy plik HTML zilustrowany obrazkami i upiększony zewnętrznym arkuszem CSS

...
<link rel="stylesheet" media="screen" href="arkuszStyli.css" type="text/css">
...
<img src="obrazki/obrazek1.png" alt="Moje zdjęcie">
...
<img src="obrazki/obrazek2.png" alt="Moja rodzina">
...

to wiemy, że jeśli przejdziemy do http://mojadomena.pl/?page=about, wszystko nadal będzie się wyświetlać jak trzeba. Gdy jednak pokusimy się o wprowadzenie przyjaznych URLi i wywołamy taki adres: http://mojadomena.pl/podstrony/about zobaczymy 'goły' plik HTML bez jakichkolwiek obrazków, czy styli.

Arghh! Jak to się stało?

Gdy wywołujesz adres http://mojadomena.pl/, a w pliku HTML masz odwołanie typu obrazki/obrazek1.png, to przeglądarka wysyła żądanie pliku, który ma się znajdować pod adresem http://mojadomena.pl/obrazki/obrazek1.png.

Ale gdy otwierasz http://mojadomena.pl/podstrony/about/, przeglądarka próbuje pobrać obrazek z adresu http://mojadomena.pl/podstrony/about/obrazki/obrazek1.png, gdzie go oczywiście nie ma.

Rozwiązanie bardzo złe

Tworzymy na serwerze strukturę katalogów, by odpowiadała żądaniom przeglądarki. Czyli tworzymy faktycznie foldery podstrony/about/, a w nich umieszczamy arkusze styli i folder obrazki z zawartością. Rozwiązanie jest fatalne, bo tworzymy sobie w ten sposób spory narzut danych na serwerze, gdzie stracone megabajty można wykorzystać w lepszy sposób. Co więcej, wyobraź sobie jaką mękę trzeba przeżywać przy aktualizacji plików. Gdy musimy wypełnić tylko 10 folderów w ten sposób, jest to jeszcze akceptowalne. Ale gdy robi się ich 50 czy 100, jest już o wiele mniej wesoło. Swoją drogą tak czasem postępują osoby, którym provider hostingu odmówił możliwości skorzystania z .htaccess i mod_rewrite. Dzięki temu mogą osiągnąć efekt przyjaznych URLi, jednak za sporą cenę miejsca na serwerze i utrudnienia sobie maintainu strony w przyszłości.

Rozwiązanie złe

Drugim ze sposobów na wyeliminowanie problemu jest podmiana wszystkich zewnętrznych odwołań na absolutne.

...
<link rel="stylesheet" media="screen" href="http://mojadomena.pl/arkuszStyli.css" type="text/css">
...
<img src="http://mojadomena.pl/obrazki/obrazek1.png" alt="Moje zdjęcie"> 
...
<img src="http://mojadomena.pl/obrazki/obrazek2.png" alt="Moja rodzina">
...

To obejście problemu też jest złe, ponieważ utrudnia ewentualne późniejsze modyfikacje struktury serwisu. Przydatne jest jedynie przy bardzo niewielkiej ilości podstron, inaczej narzut pracy spowodowany koniecznością edycji każdego odwołania może okazać się zbyt duży.

Rozwiązanie prawie dobre

Możemy zrzec się slashy (/) w adresach na kosz innych znaków, np. przecinków. Otrzymamy adresy typu http://mojadomena.pl/podstrony,about. W ten sposób problem zostanie wyeliminowany, jednak nie każdemu może odpowiadać taki sposób realizacji koncepcji przyjaznych URLi. Nie wiem jak Wy, ale mi nie podobają się takie paskudy z przecinkami. :P

Rozwiązanie dobre

Okazuje się, że można się pozbyć problemu na poziomie HTMLa. Wystarczy do sekcji head dokumentu dodać tag base i zdefiniować w nim atrybut href:

...
<base href="http://mojadomena.pl/">
...

Od tego momentu przeglądarka zacznie sobie 'doklejać' ten adres na początek każdego odwołania do zewnętrznego pliku, chyba że napotka na odwołanie bezwzględne (ftp://...., http://... itd).

Ostatni sposób uważam za najlepszy i gorąco polecam jego stosowanie. ;)

7 komentarzy »
#1 by Sharpek 31 sierpnia 2009 o godzinie 11:44 Cześć, A nie lepiej dodawać / do adresu np. /images/logo.gif zamiast images/logo.gif ? Warto też pamiętać że korzystając z narażamy się IE i tworzymy sobie problem, więcej tutaj: http://enbewu.net/browserbugs/ie/allyourbase/
#2 by HaRy 31 sierpnia 2009 o godzinie 11:46 wystarczy pamiętać, by zawsze odwoływać się do root drzewa katalogów czyli nie src="pics/foo.gif" a src="/pics/foo.gif", w CSSach podobnie.
#3 by Matix 31 sierpnia 2009 o godzinie 11:54 To rozwiązanie moim zdaniem jest także złe, conajmniej przestarzałe. Według mnie - i wielu programistów - najlepszym rozwiązaniem jest korzystanie z pełnych ścieżek, czyli to drugie rozwiązanie. (http://mojastrona.pl/about/, http://strona.pl/www/style/default.css...) Problem który tam przedstawiasz("ponieważ utrudnia ewentualne późniejsze modyfikacje struktury serwisu.";)nie jest trafiony. Nie po to mamy PHP(5) aby nie korzystać z jego możliwości. Po prostu wystarczy wykonać dwie klasy, jedną pomocniczą, jako helper widoku, i drugą - klasę dynamicznego generowania URL. Dobrym przykładem przedstawiającym takie coś jest: <body> ... <img src="<?=$this->url('about')?>"> </body> Klasa helpera będzie odwoływać bezpośrednio do klasy URL, natomiast ta będzie generować na podstawie zmiennych superglobalnych hosta, katalog i nasz param. Pozdrawiam, Mateusz Nowak.
#4 by NNPlaya 31 sierpnia 2009 o godzinie 12:24 Dzięki za komentarze i cenne wskazówki. ;) @Sharpek, przydatny link, thx. @Matix, z pewnością Twoje rozwiązanie jest warte uwagi. ;)
#5 by MWL 9 września 2009 o godzinie 15:32 Wiesz że base i podanie adresu NICZYM się nie różni? Wystarczy przecież podać stałą na początku i podawać ją jako adres. To jest właśnie zalecane rozwiązanie, nie mów więc że złe!
#6 by wojs 4 marca 2010 o godzinie 22:07 Dzięki za rozwiązanie mojego problemu NNPlaya. Głowiłem się nad nim od kilku godzin. I już myślałem, że coś mi mod_rewrite szwankuje :) A to rozwiązanie które podałeś jako dobre, jest moim zdaniem rzeczywiście najlepsze. Dlatego bo jest najprostsze :) Pozdr.
#7 by katalog stron 4 lipca 2010 o godzinie 13:36 Dzięki, rozwiązanie zwane jako "dobre" pomogło usunąć błąd wyszukiwarki IE ;)))