Ładne url'e (nice url)

2011-03-21 22:18:16
 

Dziś przedstawię Wam jak w łatwy sposób stworzyć ładne url'e we własnej aplikacji. Wielu początkujących programistów tworzy cały mechanizm ładnych url'i w całości oparty na mod-rewrite i pliku htaccess. Niestety takie podejście jest mało elastyczne i na dłuższą metę uciążliwe. Pokażę Wam inną metodę, gdzie cały mechanizm przetwarzania linków zawarty jest w kodzie php. Chcę od razu zaznaczyć, iż nie będzie tu żadnej super hiper obiektowości, rutingu i innych super hiper bajerów. Artykuł ma na celu pokazać jak prosto zrobić ładne linki i poznać podstawy tej konstrukcji.

Założenia wstępne

Na początku omówię w jaki sposób będzie kontrolowana nasza testowa aplikacja. Będzie się ona składała z modułów, zaś każdy moduł będzie miał akcje. Przykładowo możemy mieć moduł aktualności (news). Moduł ten udostępnia akcję listy aktualności (list) oraz akcję wyświetlenia konkretnej aktualności (show).

Teraz przyjmijmy, że nazwa modułu znajdować się będzie w parametrze module a akcja w parametrze action. Przykładowy standardowy link wyglądałby mniej więcej tak: index.php?module=jakismodul&action=jakasakcja

Dla naszego modułu aktualności i akcji listowania byłoby to więc tak: index.php?module=news&action=list zaś dla wyświetlenia konkretnej aktualności index.php?module=news&action=show&name=nazwanewsa&id=5 - dla konkretnej aktualności założyłem, iż potrzebna będzie jeszcze nazwa oraz id.

Mamy już linki ale jak sami widzimy są to nadal jeszcze te straszne brzydkie linki. Chcielibyśmy mieć je w ładnej postaci. Przyjmijmy więc, że nasze linki będą wyglądały tak jakismodul/jakasakcja/jakisparametr1/jakaswartosc2/jakisparametr2/jakaswartosc2. Dla naszego modułu aktualności byłoby to więc news/list oraz news/show/name/nazwanewsa/id/5

Przekierowanie adresów

Jak już mówiłem, cały mechanizm będzie oparty na php. Żeby jednak taki url jakismodul/jakasakcja/jakisparametr1/jakaswartosc2/jakisparametr2/jakaswartosc2 trafił do skryptu php, musimy go tam przekierować. W tym celu posłużę się plikiem .htaccess - wiem, mówiłem, że nie będzie potrzebny... W zasadzie to mówiłem, że nie będę tam określał reguł ładnych url'i A w tym pliku zrobimy jedynie jedno przekierowanie i nic więcej - no bez tego się nie da. Tak więc należy stworzyć plik .htaccess o następującej treści:

1
2
3
4
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)         index.php/$1 [L]

Taki zapis spowoduje przekierowanie do skryptu index.php wszelkich odwołań do zasobów naszej aplikacji, których fizycznie nie ma na dysku. No a przecież czegoś takiego na dysku jakismodul/jakasakcja/jakisparametr1/jakaswartosc2/jakisparametr2/jakaswartosc2 raczej mieć nie będziemy . No i to tyle jeśli chodzi o plik .htaccess i mod-rewrite - żadnych cudnych łamańców, których do końca nigdy nie rozumiemy i przy każdej nawet drobnej modyfikacji wyrywamy sobie włosy z głowy.

Dekodowanie adresu

Ok, to mamy już przekierowanie. Teraz trzeba taki ładny adresik przetworzyć. Nasz jakismodul/jakasakcja/jakisparametr1/jakaswartosc2/jakisparametr2/jakaswartosc2 znajdować się będzie zazwyczaj w $_SERVER['PATH_INFO']. Należy go więc stamtąd wydobyć, podzielić na podstawie "/" i przypisać wszystko do $_GET. Nie będę się tu rozpisywał co i jak tylko pokażę kod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$pathInfo 
trim($_SERVER['PATH_INFO'], '/'); //usuwamy znak / z końca
if (empty($pathInfo)) { //pusta ścieżka
    
return true;
}    
$arr explode('/',$pathInfo); //rozbijamy naszą ścieżkę na podstawie /
$count count($arr);
                
//pierwsze dwa elementy to moduł i akcja
$_GET['module'] = $arr[0];
$_GET['action'] = isset($arr[1]) ? $arr[1] : ''//tu małe zabezpieczenie, gdyby ktoś zapomniał podać akcji
        
//następne elementy to nazwy parametru i parametr i tak co dwa
for ($i=2$i $count;$i+=2){
    
$_n $arr[$i]; //nazwa parametru
    
$_v = isset($arr[$i+1]) ? $arr[$i+1] : ''//wartość parametru
    
$_GET[$_n] = $_v;
}
?>

I już. W wyniku takiego kodu, nasz link jakismodul/jakasakcja/jakisparametr1/jakaswartosc2/jakisparametr2/jakaswartosc2 zostanie prawidłowo zapisany w tablicy $_GET skąd możemy się już standardowo odwoływać do poszczególnych elementów, np: $_GET['module'], $_GET['action']...

Kodowanie adresu

Pozostało nam jeszcze tworzyć linki w naszej aplikacji. W paczce do ściągnięcia znajduje się klasa, która posiada metodę Url(). Metoda ta tworzy nam linki. Wystarczy ją tylko wywołać, np: Url('module=jakismodul&action=jakasakcja&par=war') - taki kod zwróci nam link jakismodul/jakasakcja/par/war1. A o to kod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
public function Url($path null){
if (empty(
$path)) //pusta ścieżka
    
$pars = array();
else    
    
$pars explode('&'$path);
$params = array();
foreach (
$pars as $_param){
    
$_arP explode('=',$_param,2); //par=war dzielimy na par i war
    
$params[$_arP[0]] = isset($_arP[1]) ? $_arP[1] : '';
}
$strRet '';
if (!empty(
$params)){
    foreach (
$params as $_key => $_val){
    if (
$_key == 'module' || $_key == 'action')
        
$_key '';
    else
        
$_key.='/';
    
$strRet.="$_key$_val/";
    }    
}
return 
$this->baseUrl.htmlspecialchars($strRet);    
}
?>

I tu nasuwa sie pytanie A po co przepuszczać to jeszcze przez jakąś funkcję? Czy nie można od razu wpisać sobie link taki jak chcemy? Odpowiedź: oczywiście, że można. Ale lepiej tego nie robić z bardzo prostego powodu - przepuszczanie tego przez funkcję gwarantuje nam jednolity mechanizm tworzenia linków - ustawiając jakismodul/jakasakcja zawsze otrzymamy ten sam link. No bo może się okazać, że kiedyś stwierdzicie, że dla modułu X linki mają wyglądać inaczej niż dla modułu Y. I co wtedy? Musicie ręcznie zamieniać wszystkie wstawki z modułem X. A gdyby to wszystko przechodzi przez jedną funkcję to jedyne co musicie zrobić to zmienić to i owo w tej jednej funkcji.

W paczce do ściągnięcia, rozszerzyłem właśnie trochę klasę i dopisałem inne tworzenie linków dla modułu news i akcji show. Teraz link do aktualności będzie wyglądał tak: jakas-nazwa,5.html pomimo, że wywołanie nadal wygląda tak: module=news&action=show&name=jakas-nazwa&id=5 - jedyne co musiałem zrobić to zmienić to i owo w jednej funkcji.

Podsumowanie

Zalety

  • Dowolna (dynamiczna) liczba parametrów. Przy całościowym rozwiązaniu .htaccess nie można było określić dowolnej liczby parametrów
  • Nieograniczone pole do popisu w wymyślaniu różnych kombinacji linków
  • Możliwe modułowe podejście do sprawy: każdy moduł może wnieść swój własny routing i nie trzeba nic zmieniać w plikach globalnych aplikacji. Oczywiście możliwe jest to dopiero przy odpowiednio napisanym mechaniźmie. W przykładzie co Wam udostępniam oczywiście tego nie ma

Wady

  • Nie stwierdzono

Taki mechanizm stosuję od bardzo dawna. Uratował mi skórę gdy jeszcze kiedyś robiłem wszystko w htaccess i w pewnym momencie stanąłem na coraz to bardziej zagmatwanych regółkach. Podobny mechanizm stosowany jest chyba w większości popularnych frameworkach. Mówię tu oczywiście o zarządzaniu ładnymi linkami z poziomu php a nie o dokładnie takim samym kodzie co tu pokazałem.

Paczka z przykładową "aplikacją" i klasą do pobrania jak zwykle w dziale download. Polecam jej ściągnięcie, przejrzenie i odpalenie gdyż pomoże wszystkim tym, którzy nie do końca zrozumieli ten mechanizm.

 

Komentarze

 

2011-03-22 01:22:30 gość_fl4shb4ck

 
wada jest - przy większej ilości parametrów możliwośc zmiany ich kolejności (google i inne szukajni nie będą happy - duplicated content) przykład za artykułem:

news/show/name/nazwanewsa/id/5
jest równoważne z
news/show/id/5/name/nazwanewsa

czyli mamy to samo pod dwoma adresami, rozwiazanie jest dość proste - zarówno przy tworzeniu adresów jak i przy ich przetwarzaniu można posortować parametry (a właściwie pary - klucz=>wartość) zgodnie z jakimś schematem (np alfabetycznie, od najkrótszego do najdłuższego itp) tak żeby zawsze przy generowaniu otrzymywać to samo niezależnie od danych wejściowych jak i móc wywalić 404 albo jakiś z serii 3xx w wypadku niewłaściwej kolejności parametrów - dzięki temu mamy spójny system budowania i czytania linków i cieszymy sie z lepszego indeksowania przez google

2011-03-22 06:53:41 nospor

 
Ale ten sam problem występować będzie również w systuacji, gdy wszystko robić będziemy w htaccess. A ja mówiłem o wadach i zaletach w porównaniu właśnie do htaccess
Nie mniej jednak dobrze, że o tym wspomniałeś

2011-03-22 09:47:08 gość_thek

 
Problem duplicate content da się obejść jak napisano (schemat, kolejność), albo poprzez canonical url.

2011-03-22 13:48:12 korey

 
SUPER SUPER SUPER.. Mółbyś jakoś inaczej wyróżnić te przykładowe linki np: jakismodul/jakasakcja/jakisparametr1/jakaswartosc2/jakisparametr2/jakaswartosc2
czy jakismodul&action=jakasakcja&par=war. Ale sam artykuł rewelacja

Dzięki Nospor

2011-03-22 14:04:14 nospor

 
Mółbyś jakoś inaczej wyróżnić te przykładowe linki
Mówisz masz

2011-03-22 14:19:52 korey

 
No teram to jestem w pełni zadowolony

2011-03-22 16:11:36 gość_ytjui

 
Ale wazelina

2011-03-22 22:04:46 gość_Fifi209

 
"Ale ten sam problem występować będzie również w systuacji, gdy wszystko robić będziemy w htaccess."

Nie będzie, bo jeżeli ustalisz regułkę w postaci np. :
(news)/(show|edit)/([0-9]+) index.php?model=$1&action=$2&id=$3

To po wpisaniu show/9/news dotrzesz do 404 o ile się nie mylę ;p

Jeżeli się mylę, to mnie popraw a ja zwracam wtedy honor. ;p

2011-03-23 06:45:41 nospor

 
@Fifi209 ale tak samo mogę ustawić w php i też wtedy problem nie wystąpi. Mówimy tu o ogólnym przypadku. Każdy inny szczególny można i tu i tu ustawić

2011-04-01 20:12:33 gość_szil

 
nie widze tej paczki w download

2011-04-02 20:37:49 nospor

 
download -> kody do artykułów -> ladneurl-niceurl.zip

2011-04-08 18:45:36 gość_trs

 
witam, a jak jest na najpopularniejszych polskich serwerach hostingowych? modul rewrite jest wlaczony czy nie?

2011-04-09 19:16:25 gość_ktos

 
Opcja ta jest raczej dostępna wszędzie. Korzystałem już z wielu hostingów i wszędzie była.

2011-05-12 20:04:05 gość_barthek

 
Trafilem przez przypadek, ale jedna uwaga - gdy w URLu mamy nazwy parametrow, to niestety nie mozna tego nazwac przyjaznym linkiem. Tzn takie cos:
domena.pl/modul/akcja/param1/value1/param2/value2
nie do konca jest przyjaznym linkiem.. Przyjazne to dopiero bedzie jak link bedzie wygladal tak:
domena.pl/modul/akcja/value1/value2

Jednak zeby nam to dzialalo konieczne jest rejestrowanie zmiennych GETowych osobno dla kazdej naszej akcji (albo ogolniej - dla modulu, gdzie parametr akcji jest jedna ze zmiennych GETowych). Nieco ciezsze w implementacji, ale jakie efekty

2011-05-16 11:08:50 nospor

 
@barthek ale to o czym mówisz można bez większego problemu zaimplementować w metodzie, którą tutaj opisałem. Ja przedstawiłem tutaj jedynie dwa wariany (z parametrami oraz strony .html). Ale można tutaj włożyć całą masę innych wariantów.

2011-05-18 07:57:43 nospor

 
Dla wszystkich tych, którzy nie chcą mieć linków z modułami a tylko z parametrami, czyli zamiast jakismodul/jakasakcja/par1/war1/par2/war2 chcecie mieć par1/war1/par2/war2 podaję co należy zmienić w pliku NUrl.class.php :

W lini 54 jest
1
2
3
4
<?php
$_GET
['module'] = $arr[0];
$_GET['action'] = isset($arr[1]) ? $arr[1] : ''//tu małe zabezpieczenie, gdyby ktoś zapomniał podać akcji
?>


Trzeba to poprostu zakomentować
1
2
3
4
<?php
//$_GET['module'] = $arr[0];
//$_GET['action'] = isset($arr[1]) ? $arr[1] : ''; //tu małe zabezpieczenie, gdyby ktoś zapomniał podać akcji
?>


Linijkę niżej jest pętla:
1
2
3
<?php
for ($i=2$i $count;$i+=2){
?>


Trzeba w niej zmienić 2 na 0
1
2
3
<?php
for ($i=0$i $count;$i+=2){
?>


Oraz w linii 87 jest:
1
2
3
4
5
6
<?php
if ($_key == 'module' || $_key == 'action')
  
$_key '';
else
  
$_key.='/';
?>


Trzeba zakomentować 3 pierwsze linie:
1
2
3
4
5
6
<?php
//if ($_key == 'module' || $_key == 'action')
//  $_key = '';
//else
  
$_key.='/';
?>

I już

2011-05-19 06:39:55 gość_Artur

 
Witam, czy da rade przerobić taki .htaccess na ten "nice url"?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
RewriteRule ^profil,potwierdz,kod,(.*).html$ konto.php?opcja=potwierdz&kod=$1 [NC]
RewriteRule ^profil,wyloguj.html$ konto.php?login=koniec [NC]
RewriteRule ^profil,([a-z]+).([a-z]+).html$ konto.php?opcja=$1-$2 [NC]
RewriteRule ^profil,([a-z]).html$ konto.php?opcja=$1 [NC]
#strony
RewriteRule ^sc.([0-9\.]+).html$ sc.php?sid=$1 [NC]
RewriteRule ^home$ index.php?s=home [NC]
RewriteRule ^strona,([a-z]+).html$ index.php?s=$1 [NC]
RewriteRule ^strona,([a-z]+).([a-z]+).html$ index.php?s=$1-$2 [NC]
#linki dla administratora
RewriteRule ^admin,([a-z]+).html$ index.php?s=admin_$1 [NC]
RewriteRule ^admin,([a-z]+).([a-z]+).html$ index.php?s=admin_$1-$2 [NC]
#inne
RewriteRule ^wiadomosci,([odebrane|archiwum]+).([0-9\.]+).html$ wiadomosci.php?folder=$1&sid=$2 [NC]
RewriteRule ^wiadomosci,([archiwizuj|banuj|usun]+).([0-9]+).html$ wiadomosci.php?akcja=$1&id=$2 [NC]
RewriteRule ^strona,komunikator.stan.([0-9]+).html$ index.php?s=komunikator&stan=$1 [NC]

2011-05-19 07:22:18 nospor

 
U Ciebie jest ten problem, że nie masz jednego głównego skryptu. Raz to jest index.php, raz wiadomości.php a innym znowu razem sc.php

Aplikacja powinna mieć jeden główny plik i to on powinien zarządzać całością. Gdybyś tak miał, to bez większego problemu można każdą z tych regułek przepisać na podobny ruter co tutaj.

2011-05-19 17:43:56 gość_Artur

 
mogę prosić o zdiagnozowanie, czemu z tym htaccess moim, działa mi link: wiadomosci.php?akcja=banuj&id=2
a nie działa wiadomosci,banuj.2.html
z podobnymi linkami z akcją archiwizuj i usun po operacji przeadresowania nie ma problemów.

2011-05-20 07:48:27 nospor

 
Nawiasy kwadratowe służą do wyznaczania zbioru znaków a nie słów.
Nie:
RewriteRule ^wiadomosci,([archiwizuj|banuj|usun]+).([0-9]+).html$ wiadomosci.php?akcja=$1&id=$2 [NC]
a:
RewriteRule ^wiadomosci,(archiwizuj|banuj|usun).([0-9]+).html$ wiadomosci.php?akcja=$1&id=$2 [NC]

2011-05-31 17:19:41 gość_Gidaban

 
Witam

Bardzo fajna klasa ale mam jedno pytanie co w przypadku jak ma się więcej modułów a chce się mieć linki .html?


pozdrawiam

2011-06-01 13:46:10 nospor

 
No linki .html pokazałem w paczce na przykładzie newsów.
Jeśli zaś chodzi ci o to, że każdy moduł może dostarczać własny ruter, to trzeba by klasę zmodyfikować o możliwość podczepiania ruterów innych modułów. Tutaj pokazałem pewien podstawowy mechanizm. Chcąc mieć więcej trzeba go poprostu rozbudować

2011-06-03 07:52:55 gość_Artur

 
dzięki działa

2011-06-04 03:03:10 gość_Artur

 
No dobrze zmieniłem swój skrypt, teraz wszystko wychodzi z index.php czy trzeba cos zmieniać aby poniższe linki zamienić na to co po "->":

1
2
3
4
index.php?page=admin&folder=main -> /admin/main
index.php?page=regulamin-strony -> /pokaz/regulamin-strony
index.php?page=wiadomosci -> /wiadomosci
index.php?page=wiadomosci&folder=odebrane&sid=323233412312 -> /wiadomosci/odebrane/323233412312

2011-06-04 13:23:04 nospor

 
Jeśli mówimy o mojej klasie co tu pokazałem i nie chcesz w niej nic zmieniać, to linki powinienieś zmienić by zawierały parametr module oraz action

2011-06-04 14:02:54 gość_Artur

 
no właśnie nie chce korzystać z module oraz action, zakomentowałem to co napisałeś w komentarzach, co i gdzie muszę zmienić w Twojej klasie aby ładnie w niej działały moje linki ?

2011-06-04 14:18:13 nospor

 
Jeśli skorzystałeś tego zmienionego kodu, co podałem w komentarzach, to wówczas taki kod:
/admin/main jest zamieniany na taki: index.php?admin=main
/pokaz/regulamin-strony na taki: index.php?pokaz=regulamin-strony
Także trochę nie pasuje do tego co masz. Albo więc bez zmieniania mojej klasy zmienisz swoje linki, albo musisz zmieniać w klasie.

2011-06-30 14:22:19 gość_zozol

 
"jakas-nazwa,5.html" - Gdzie 5 to id newsa wyciągniętego z bazy. A jak to zrobić tak jak Ty masz tu na stronie, czyli
"jakas-nazwa.html" ?

2011-07-01 08:43:57 nospor

 
Chodzi ci o stworzenie linka czy obsługę?

2011-07-03 11:05:40 gość_zozol

 
Chodzi mi o caly proces. Jak taki link jest tworzony a nastepnie jak np. klasa routerowa obsluguje takie linki w których prawie nic poza nazwa nie zostaje podane. Bardzo bym prosił o wytlumaczenie lub jakie kolwiek nakierowanie, bo tez chciał bym zaopatrzyc swoja strone w takie linkowanie

2011-07-03 11:08:29 gość_zozol

 
Pozwole sobie napisac: U mnie na stronie linkowanie wyglada w ten sposób: domena/nazwa-kontrolera/nazwa-akcji/parametr1/parametr2 i na podstawie takiego linku router rozbija mi go i przypisuje konkretne wartosci do zmiennych, na podstawie ktorych pozniej silnik wie ktore pliki i metody zaladowac.

2011-07-03 12:38:51 nospor

 
Cały proces wygląda analogicznie jak z podaniem id.
w przykładzie podałem: nazwastrony,idstrony.html
Jeśli chcesz mieć tak jak u mnie, czyli nazwastrony.html to:
1) W bazie danych musisz przechowywać tę nazwę dla strony i ta nazwa musi być unikalna. Ja nazwy stron tworzę automatycznie biorąc tytuł i wywalam z niego polskie znaki, spacje itp.
2) Dla linku strony podajesz tylko nazwe. Ruter widzi, że w adresie jest nazwastrony.html i przekierowuje na akcję "pokaż stronę" - analogicznie tak jakby tam było jeszcze id.
3) Akcja "pokaż stronę" zamiast pobierać stronę na podstawie id to pobiera stronę na podstawie nazwy.

2011-07-03 21:22:00 gość_zozol

 
Dzieki.. bardzo, Dużo mi pomogłeś!

2011-08-22 08:57:06 gość_laska

 
Dobry artykuł.
Ta metoda klejenia jest bardzo wygodna i efektywna. Troszkę trudniejszą sprawą jest tworzenie linków na wzór:

jakasmodulpoprzedni1/jakasmodulpoprzedni2/wlasciwymodul/akcja/wartosc1/wartosc2

Jeśli chcemy aby nasze linki dostarczały wyszukiwarce więcej słów kluczowych jak np:

ogloszenia/motoryzacja/osobowe/tanie/audi-A4-2005/45006

Ja mam obecnie tak zaimplementowany system ale niestety bez użycia routera sprawdzającego kolejne parametry i szukającego najbardziej pasującego ciągu chyba się nie obejdzie.
Macie jakiś inny pomysł na taką implementację ?

2011-08-22 10:44:03 nospor

 
Na podstawie tego ciągu:
audi-A4-2005/45006
wiesz że chodzi o samochód. Teraz poprostu robisz explode() po / na ogloszenia/motoryzacja/osobowe/tanie i już masz kolejne parametry opisu.

2011-08-22 22:40:52 gość_laska

 
Ale skąd masz pewność że ten ciąg to dział ogłoszeń jeśli w serwisie prowadzisz również katalog firm i forum ? Ciągi mogą się zgadzać tu i tu więc po ścieżce od lewej musisz dojść do ostatniego parametru zawierającego moduł.

według wyrażeń adres np:

ogloszenia/motoryzacja/osobowe/tanie/audi-A4-2005/45006

..będzie tym samym co temat na forum:

kobieta/kosmetyki/firmowe/tanie/zara-X6-3000/345435

...lub wpis w katalogu:

budowlane/ogrod/rosliny/poznan/franspol/3243534

Rozróżnienie tylko przedostatniego parametru jako działu będzie samobójstwem, ponieważ ryzykowne będzie założenie że treści ogłoszenia lub tematu na forum będzie w stałym schemacie. Zmienisz lekko schemat generowania tytułu ogłoszenia i klapa.
Dlatego to ścieżka poprzedzająca a dokładnie ostatni parametr MODUŁOWY powinien dać Tobie informacje na temat id działy/pliku wykonywalnego. Ja to rozwiązałem poprzez Router który porównuje od lewej każdy parametr adresu z ścieżkami zapisanymi już w routerze na przykład z bazy. Dzięki temu mogę tworzyć adresy na wzór: moduł1/moduł2/parametr lub też moduł1/moduł2/moduł3/moduł4/moduł5/parametr/parametr i każdy przypadek będzie działał ponieważ odszuka mi pasującą ścieżkę do wszystkich parametrów
Minus to czas jaki potrzebuje kompilator na znalezienie odpowiedniej ścieżki, aby to zredukować zastosowałem cache na generowaniu linków i problem zostaje rozwiązany, choć wciąż szukam jeszcze jakiegoś innego rozwiązania.

2011-08-23 07:33:27 nospor

 
No a czemu nie dasz jakiegoś przedrostka, określającego co jest co? Przecież to nie zaszkodzi

ogloszenia/motoryzacja/osobowe/tanie/audi-A4-2005/m-45006
kobieta/kosmetyki/firmowe/tanie/zara-X6-3000/f-345435
budowlane/ogrod/rosliny/poznan/franspol/k-3243534

I już. Po końcowóce będziesz widział że to jest motoryzacja, forum czy katalog.

2011-08-23 09:08:13 gość_laska

 
Nie podchodzi mi taka kombinatoryka, ponieważ z doświadczenia wiem że to rozwiązanie do czasu kiedy przyjdzie mi generować inny schemat url. Zresztą nie muszę mieć identyfikatora strony.
Przy moim założeniu mogę generować działy zarówno takie:

/ogloszenia/motoryzacja/osobowe/tanie/audi-A4-2005/m-45006

jak i :

/kontakt lub oferta/budowlane

gdzie nigdzie nie mam żadnych identyfikatorów aby url ładnie wyglądał, system i tak znajdzie odpowiednią ścieżkę do działu tekstowego budowlane.

2011-08-23 09:25:37 nospor

 
Nie podchodzi mi taka kombinatoryka, ponieważ z doświadczenia wiem że to rozwiązanie do czasu kiedy przyjdzie mi generować inny schemat url.
I dlatego właśnie tutaj w arcie przedstawiłem jedną klasę do generowania i odbierania linków. Dzięki temu, nawet jak nagle komuś zachce się zmieniać schemat linków to zmiany robi tylko w tej klasie nie ruszając w ogóle reszty kodu aplikacji.

2011-08-23 13:46:02 gość_laska

 
Celem jest nie modyfikowanie w ogóle klasy

2011-08-23 13:47:14 gość_laska

 
Poza tym przypadek który poruszyłem dotyczy tego samego serwisu wiec zmiana w klasie nie wchodzi w grę. Działy tekstowe maja adresy /oferta/costam a dział ogłoszeń /ogloszenia/motoryzacja/osobowe/tanie/audi-A4-2005/45006

2011-08-26 21:41:41 Michał

 
Witam,
Sporo myślałem nad idealną klasa routera. Stwierdziłem, ze nie może to być jedna klasa. Doszedłem również do wniosku, że nie da się zrobić bez konfiguracji linków super krótkich, po którym wiedziałbyś, że /kontakt.html to moduł page kontroler page i akcja contactForm, a strona /o-mnie.html to moduł page kontroler page i akcje show.

Musimy zrobić router, który by to wszystko pamiętał. Skoro ma pamiętać, to gdzie?
- Baza danych - Każdy link w bazie a dane o kontrolerach wyciągamy z bazy
- System plików - zapisujemy sumę kontrolną linku jako nazwę pliku a tam czeka na nas zserializowana tablica z parametrami, który moduł/kontroler/akcję odpalić.

Nie chciałbym mieszać do tego bazy danych bo po co mi przy prostej stronce jedno zapytanie więcej?
Wszystko piszę tak, aby siedziało w cache(nawet ja dodaje coś w panelu to panel odświeża cache, więc jak zdarzy mi się kilka zapytań na dzień to jest max)

Jestem ciekawy jak wy rozwiązaliście ten problem, a szczególnie Ty Nosporze.

Póki co u mnie do routera wstrzykuję różne wzorce z configu, które są porównywane z adresem i na tej podstawie wiem co odpalić(frontend). W backendzie mam linki: /moduł/kontroler/akcja/param/value/

Ostatnio próbowałem zaimplementować Uploadify do łatwiejszego wgrywania plików i oto na co napotkałem - Error 404. Po prostu pod Firefoxem flash z uploadify otwierając php tworzy nową sesję(wiedziałem o tym - akurat do obejścia, pod IE wszystko ok) i nie akceptuje linku w formacie, który wyżej podałem. Więc musiałem do routera dodać hook, żeby można było korzystać z normalnych parametrów GET. Myślałem, że będzie ok ale zdziwiłem się jak tylko pierwszy parametr z $_GET trafił do skryptu uploadującego! Nie dałem za wygraną i wstrzyknołem do routera nowy mechanizm, który pozwala tworzyć linki w tym formacie: http://localhost/admin-page-edit-lang-pl-module_id-2-mode-uploadattachment-id-2-session-vsnbjiikb11pfh3p5btojvo683.php. Wszystko działa.

Czekam na wasze rozważania dotyczące routingu. Dodam, że nawet programiści z MyBB zaimplementowali nice urls w bazie danych

Pozdrawiam

2011-08-26 21:46:10 Michał

 
A tak nawiasem mówiąc to witam po dłuższej przerwie po zdradzie PHP z C

2011-08-27 13:00:01 nospor

 
U mnie produkcyjnie to jest jedna klasa, podobna do tej tutaj.
Z jedną "małą" różnicą: klasa pozwala na dodawanie ruterów innych modułów. Czyli moduł X dodaje do klasy swój ruter, moduł Y dodaje do klasy swój ruter itd. Później klasa leci pokolei z ruterami i jeśli któryś z ruterów uzna, że dany link jest jego to go obsługuje i dalsze ruterty już danego linka nie ruszają.

Dzięki temu rozwiązaniu mogę spokojnie pisać modułowo i nie martwić się, że nagle w core będę musiał obsłużyć linki z jakiegoś modułu.

, po którym wiedziałbyś, że /kontakt.html to moduł page kontroler page i akcja contactForm, a strona /o-mnie.html to moduł page kontroler page i akcje show

Ja akurat z tym nie mam problemu. Każda strona normalna.html to akcja cms. A to czy do tej strony będzie dołączony np. formularz kontaktowy czy coś innego to ja to ustawiam na poziomie cms.

ps: zdrada wybaczona

2011-08-27 14:06:55 Michał

 
Ja akurat z tym nie mam problemu. Każda strona normalna.html to akcja cms. A to czy do tej strony będzie dołączony np. formularz kontaktowy czy coś innego to ja to ustawiam na poziomie cms.


Ale żeby wiedzieć co podpiąć do stronki kontakt.html to system leci do bazy/cache i bierze sobie z niego dane co ma odpalić(tekst/galerię/formularz kontaktowy)?

Jeżeli tak to zapewne masz tabelę PAGES i tam trzymasz identyfikatory stron, czyli trzeba wmieszać do linków bazę danych

pzdr

2011-08-27 14:15:45 Michał

 
Odnoście: $_SERVER['PATH_INFO'] to ja la lokalnym nie mam tej zmiennej w tablicy $_SERVER.
Więc trzeba wrzucić kilka parametrów i jak któryś istnieje to z niego korzystamy.

PHP Version 5.3.6

2011-08-27 21:06:54 nospor

 
Ale żeby wiedzieć co podpiąć do stronki kontakt.html to system leci do bazy/cache i bierze sobie z niego dane co ma odpalić(tekst/galerię/formularz kontaktowy)?
Albo Ja cię nie kumam, albo na odwrót

Na podstawie linku kontakt.html wiem, że mam odpalić akcję show w module cms z parametrem name=kontakt. I tyle. Link został rozwiązany. A co zrobić akcja show w module cms to już jej sprawa.

2011-08-28 18:02:32 Michał

 
Ale żeby wiedzieć co podpiąć do stronki kontakt.html to system leci do bazy/cache i bierze sobie z niego dane co ma odpalić(tekst/galerię/formularz kontaktowy)?

Albo Ja cię nie kumam, albo na odwrót

Na podstawie linku kontakt.html wiem, że mam odpalić akcję show w module cms z parametrem name=kontakt. I tyle. Link został rozwiązany. A co zrobić akcja show w module cms to już jej sprawa.


OK, rozumiem. Masz zrobione to "na sztywno". Chciałbym wiedzieć, czy w twoim CMS jest taka możliwość, ze inny moduł korzysta z końcówki .html czy tylko moduł cms jest do tego uprzywilejowany?

2011-08-29 07:47:57 nospor

 
Nie, końcówka .html nie jest przeznaczona dla cms.
Weź np. moduł forum:
http://forum.nospor.pl/programowanie/php-ff5.html
http://forum.nospor.pl/programowanie/php/zabezpieczenie-skryptu-ft222.html
Też mają końcówkę .html. Tylko zauważ, że dla forum końcówka wygląda tak: -ffLICZBA.html, -ftLICZBA.html
I już. Na tej właśnie podstawie rozróżniam co jest cms a co jest forum. Żadne zapiski w bazie tu nie są potrzebne.

2011-08-31 18:39:21 gość_bigzbig

 
Trochę to archaiczne, ale grunt że działa i jest sprawdzone. Ja od czasu kiedy poznałem Django zastanawiałem się dlaczego w PHP nie można zrobić podobnego routingu jak w przytoczonym frameworku. Okazało się, że można choć nie daję głowy, że z wszędzie i zawsze.

http://blog.heintze.pl/2011/08/31/nice-url-przyjazne-linki/

2011-09-01 08:17:51 nospor

 
No u siebie ja też używam wyrażeń regularnych. Tutaj jednak pisałem arta bardziej z myślą o początkujących użytkownikach i nie chciałem wyrażeń w to mieszać. Może moje założenie było błędne. Ale chodziło mi głównie o przedstawienie ogólnego mechanizmu.

2011-09-01 16:39:55 gość_eccocce

 
Hej nospor,
Ciekawe rozwiązanie, właśnie staram się wrzucić je u siebie.
1
$pathInfo trim($_SERVER['PATH_INFO'], '/'); //usuwamy znak / z końca

Wyrzuca Notice, gdy jest pusty URL.

Poza tym, gdy dodam / na koniec URL-a to cuda się dzieją. Zacząłem wątek o tym na forum:
http://forum.php.pl/index.php?showtopic=183383

Jeśli masz jakąś radę, to będę wdzięczny.
Pozdrawiam

2011-09-01 17:02:26 nospor

 
Zauważ, że u mnie w kodzie jest:
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
//w zależności od serwera nasza scieżka może się znajdować pod innym indeksem
        
if (!empty($_SERVER['PATH_INFO']))
            
$_pi $_SERVER['PATH_INFO'];
        if (empty(
$_pi) && !empty($_SERVER['ORIG_PATH_INFO']))
            
$_pi $_SERVER['ORIG_PATH_INFO'];
            
        
$pathInfo trim($_pi'/'); //usuwamy znak / z końca
        
if (empty($pathInfo)) { //pusta ścieżka
            
return true;
        }    
?>

2011-09-01 17:04:59 gość_eccocce

 
No tak, wziąłem kod prosto ze strony zamiast z downloadu.

2011-09-01 17:09:49 nospor

 
Faktycznie... na stronie dałem wersję light
Poza tym, nie mam problemu co ty masz, że gdy na końcu będzie / to strona szaleje. Nawet w paczce w download masz działający skrypt, który zawiera własnie linki z / na końcu i wszystko działa. Sprawdź to u siebie. To jest gotowa paczka do odpalenia

2011-09-01 17:39:40 gość_eccocce

 
Wziąłem paczkę ze strony i jest ta sama sytuacja.
Wrzuć sobie do folderu z rozpakowanymi plikami np. folder img i tam plik logo.png
W 25. linijce pliku index.php dodaj:
1
2
echo '<img src="img/logo.png" alt="" />';

Jak wywołasz adres/test to obrazek pokazuje się, a jak już adres/test/ to znika...
Skrypt z plikiem graficznym i tą dodatkową linijką wrzuciłem tutaj jakbyś chciał szybko przetestować. http://szkolea.pl/nospor.zip

Tutaj na stronie wykorzystujesz tę samą wersję, czy "bogatszą"?

2011-09-01 20:47:49 Michał

 
Ajć, szkolny błąd. Poczytaj o sposobie przypisywania linków w html a dużo się dowiesz.
Słowa kluczowe: meta tag base, ścieżki bezwzględne

Pozdrawiam

2011-09-02 08:02:30 nospor

 
Mi tam Twój kod działa dobrze niezależnie od adresu.
Aczkolwiek Michał dobrze napisał - lepiej podawać pełne linki do zasobów. Spróbuj z pełnym liniem i daj znać jak teraz.

2011-09-02 20:19:30 gość_eccocce

 
Ścieżki bezwzględne zostawiłem sobie jako ostateczność Myślałem, że problem leży w czymś innym, bo sugerowałem się tym, że np. Ty nosporze w CSS tej strony używasz ścieżek względnych (używasz tagu base?). W każdym razie dziwne, że ten mój kod Ci działa niezależnie od adresu...
Wrzuciłem ścieżki bezwzględne i wszystko ładuje się bez problemu!
Dzięki jeszcze raz nospor za skrypt.

2011-09-02 20:21:32 nospor

 
Nie, nie... w css można używać ścieżek względnych - akurat w css to działa bez zarzutu. Natomiast w kodzie strony lepiej podawać pełne ścieżki. Kiedyś bawiłem się tym cudem BASE, ale w praktyce okazało się, że ma to więcej wad niż zalet i zaprzestałem używania tego.

2011-09-02 22:09:35 Michał

 
Fajne rozwiązanie to kompilator do styli/cacheowanie ich i wtedy masz fajne pole do popisu do ścieżek bezwzględnych nawet w kodzie css.

Pozdrawiam

2011-09-04 17:03:46 gość_eccocce

 
Coś nie dodałem się mój komentarz... Napiszę jeszcze raz.

W kodzie strony, przed każdą ścieżką do obrazka/pliku JS/pliku CSS dodałem zmienną, a przy generowaniu strony podmieniam zmienną na taki kod:

1
2
$var 'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']).'/';


No i póki co działa. Nie chciałem na sztywno wpisywać wszędzie ścieżek, bo przy przeprowadzce byłby problem...

Mam nadzieję, że teraz uda się dodać komentarz

2011-12-06 20:12:31 gość_Robson

 
Dzięki przyda się artykuł i to bardzo, bo właśnie jestem w trakcie zmiany swoich adresów na stronce.

2012-01-24 21:19:09 gość_siutek

 
witam, probuje zaimplementować to u siebie, ale plik .htaccess spreparowany jak wyżej powoduje błąd serwera 500, w logach widzę taką oto linijkę:

.htaccess: Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration

czegoś mi brakuje?

pakiet XAMPP, php 5.3.5

2012-01-24 21:26:34 gość_siutek

 
eee, dobra, z tym blede sobie poradzilem, skrypt ładnie wyłapuje do zmiennych wszystkie parametry, tak jak nalezy. niestety nie wiem czemu nagle posypała mi się cała grafika - pogubił ścieżki, do css'a i nie tylko

katalog pix znajduje się wewnatrz katalogu ze stroną, jednak serwer mysli ze /pix/ ma lokalizację wewnątrz http://localhost/strona/modul/akcja/param1/wartosc1/ - tak jakby to byla sciezka katalogow :/

2012-01-24 21:40:06 gość_siutek

 
qrcze, troche za szybki jestem w pisaniu, i na powyzszy problem znalazlem rozwiazanie

<base> w sekcji head i wszystko smiga!

sorki za potok komentarzy

2012-01-25 08:50:43 nospor

 
<base> nie jest najlepszym pomysłem. Prędzej czy później się na nim przejedziesz. DLa css, js i obrazków podawaj pełne ścieżki dostępu a nie skrótowe. Wówczas nie będziesz miał z niczym problemów

2012-01-29 18:14:59 gość_siutek

 
dlaczego <base> jest zlym rozwiazaniem? w jakich okolicznościach bede mial z nim problemy?

2012-01-30 08:09:13 nospor

 
Nie podam ci teraz konkretnego przykładu. Parę lat temu sam używałem base i byłem z niego zadowolny. Potem nagle pojawił się pewien problem, naprawdę nie pamiętam jaki, ale wiem, że miałem z nim sporo kłopotu.

O wiele bezpieczniejsze i pewniejsze jest używanie pełnych ścieżek.

Dodaj komentarz

 

Dostępne bbcode: b, u, i, color, size, quote, img, url, list, il (tylko w list), code, php, css, html, sql, js