ďťż

[PHP] Krótkie URL - teoria ciąg dalszy - kompatybilność, system plików

       

Podstrony


telcocafe

Chcę jak najszybciej wprowadzić obsługę krótkich URL. Dzisiaj to podstawa. Nie jestem przekonany, czy wpływa to na pozycję w wyszukiwarkach, ale na pewno zyskają użytkownicy systemów statystyk, a adresy będą bardziej czytelne.

Postaram się wyjaśnić zagadnienia szczegółowo, by każdy zrozumiał. :)
Będę zadawał pytania oznaczone numerami - 1), 2)...

Kompatybilność
Dotychczasowe adresy w stylu index.php?co=modul&act=send w wersji krótkiej mogą wyglądać tak: /modul/send. Prawda, że czytelniejsze? Rezygnując jednak ze starej postaci URL-ów należałoby zerwać kompatybilność. Nie do końca. Można napisać konwerter starych adresów, który zamieni je na nowe.

Dobrze, ale jeśli brakuje mod_rewrite?
Przecież zostanie tylko stary format URL. Jak w takim razie wygenerować odnośnik do innej podstrony? Można tak:
$url = (MOD_REWRITE) ? '/modul/send' : '?co=modul&act=send';
A może istnieje sposób na implementację krótkich URL na serwerach bez mod_rewrite? Wpadłem na pomysł, aby wykorzystać system plików. Na pewno w CMS-ach taka metoda jest od dawna wykorzystywana, choć jeszcze nie spotkałem się z tym.

Gdy nadchodzi żądanie do /modul/send, CMS próbuje znaleźć plik send w folderze modul. Zawiera tylko komendy startowe i ewentualnie cache niektórych elementów bądź zapytań z bazy danych.chdir('..'); /* budowanie tablicy $URL i inne wymagane operacje */ require 'index.php';
A może inny separator?
Aby uniknąć problemu ze zmianą bieżącej ścieżki w przeglądarce, część skryptów zamiast / dzieli składniki URL za pomocą innego znaku, np. przecinka. Rozważmy przykład: jesteśmy na stronie domena.com/modul/send. W menu są odnośniki do innych stron, np. innastrona.html. Po kliknięciu linku strona nie otworzy się, gdyż przeglądarka przekieruje do domena.com/modul/innastrona.html zamiast domena.com/innastrona.html.

Gdy wykorzystamy inny separator - domena.com/modul,send - powyższy problem nie wystąpi. Jednak obawiam się, czy idea oparcia krótkich URL na systemie plików wypali. Główny katalog będzie musiał mieć prawa zapisu.

Wróćmy do standardowego separatora - czyli ukośnika / - można rozwiązać problem na 2 lub więcej sposobów. Podam od razu ich zalety i wady.

A. Znacznik <base>

Określa katalog bazowy. Dobre rozwiązanie, gdy w kodzie HTML i CSS są URL-e względne, np. img/obraz.png, lib/js.js.

B. Ścieżki bezwzględne

Należy rozpocząć każdy URL od ukośnika, np. /img/obraz.png, /lib/js.js. Co wtedy, gdy witryna znajduje się w podkatalogu, np. jakishosting.com/twoja_strona? Wtedy ścieżki będą wyglądać tak: /twoja_strona/obraz.png, itd.

Implementacja krótkich URL w PHP
Zamiast definiować wiele reguł w .htaccess i przerabiać je na formę ?co=modul&act=send, można przekierować wszystkie żądania (które nie odnoszą się do istniejących plików) do strony: index.php?url=modul/send. Teraz łatwo pociąć URL:$URL = isset($_GET['url']) ? explode('/',$_GET['url']) : array('');
Teraz wykorzystujemy tablicę numeryczną $URL do wyświetlenia odpowiedniego modułu.

Elastyczność
Cel: brak problemów przy przenosinach serwisu na inny serwer, nieutrudnianie życia redaktorom strony... Nie każdy może pamiętać lub chcieć podawać wszędzie ścieżki bezwzględne (zaczynać od /). Może nawet nie będzie rozumiał / wiedział.

Indeks URL
CMS oferuje wiele modułów. Można go rozszerzać za pomocą rozszerzeń. Domyślnie oferuje 5 typów treści: artykuły, pliki, multimedia, linki i nowości. Dodajmy jeszcze inne elementy, które mają TYTUŁY: kategorie, ankiety...

Najprościej tworzyć takie URL-e dla treści: /artykul/50, /plik/99, /50 (kategoria)
albo takie: /artykul/skrocony-tytul, /plik/tytul-pliku, /tytul-kategorii (kategoria)

Można jeszcze bardziej skrócić URL-e, stosując globalny indeks skróconych tytułów. Nie wiem, czy wszyscy będą w stanie zrozumieć, czym jest skrócony URL, jeśli zobaczą takie pole w formularzu - nawet mimo wyjaśnień. Nic nie stoi na przeszkodzie, aby generować je automatycznie.

domain.com/tytul-artykulu, domain.com/tytul-pliku, domain.com/tytul-kategorii

Możliwe konflikty:

A. Ten sam tytuł w różnych wersjach językowych strony - może to być tytuł skryptu lub programu. Zdaje się, że łatwo go obejść - skrypt wczyta artykuł / plik / ... dla używanego języka (jeśli istnieje).

B. Te same tytuły dla różnych typów zawartości - np. taki sam tytuł ma obraz, artykuł, itd.

Dalsza dyskusja
Na pewno nie wymieniłem wszystkich zagadnień związanych z krótkimi URL, dlatego zachęcam do dalszej dyskusji.

1) Czy da się po stronie serwera podmienić adresy URL tak, aby były wczytywane względem ścieżki bazowej?

Przykład: przeglądarka wysyła żądanie do: domena.com/modul/start, a serwer jest w stanie załadować index.php znajdujący się w głównym katalogu, a nie do strony 404 (?)

2) Co sądzicie o wykorzystaniu systemu plików?

3) Ścieżki bezwzględne, <base>, czy inne rozwiązanie?

4) Co sądzicie o globalnym indeksie URL? Czy to dobry pomysł?

5) Skomentujcie poszczególne aspekty / problemy opisane w powyższych akapitach.



W PHP możesz użyć preg_replace_callback i ob_start do automatycznego przepisywania zwykłych URLi na "przyjazne"- Krótkie URLe i PHP. Możesz też zastosować rozwiązanie zbliżone do tych stosowanych przez frameworki napisane w Pythonie czy Ruby - mapując ścieżkę żądania na odpowiedni widok/kontroler - na forum.php.pl ktoś ostatnio podawał taki przykład (nie wymaga to mod_rewrite).
Użytkownik Riklaunim edytował ten post 29 październik 2009, 17:34
Buforowanie wyjścia z funkcją zamieniającą URL-e nie gwarantuje, że zostaną zamienione wszystkie adresy. Ciężko przewidzieć, gdzie się znajdują i w jakiej postaci - np. w skryptach JS.

Zacząłem zmieniać URL-e w skrypcie na następujące: art/50, pms/edit/40... Ścieżka jest w <base/>. W ten sposób, że:$URL = isset($_GET['path']) ? explode('/', $_GET['path']) : array();Wstrzymałem się, aby nie porywać się z motyką na słońce.

1. Chcę koniecznie wspierać serwery bez obsługi MOD_REWRITE bądź PATH_INFO. Czy obrałem rzeczywiście dobrą drogę? Na takich hostingach pozostaje sposób z systemem plików lub tradycyjny index.php?path=modul/akcja/id.

Pytanie, czy jest sens rezygnować ze starej formy: ?co=modul&id=55 na nową: ?path=modul/55

Gdy jest dostępny mod_rewrite...

W pierwszym przypadku trzeba napisać kilka reguł RewriteRule, aby objąć adresy o różnym stopniu skomplikowania, np. ?d=4, ?co=poll&id=2, ?co=pms&act=edit&id=99... W drugim przypadku wystarczy 1 reguła RewriteRule, a w PHP taki adres musi zostać pocięty na części (np. na tablicę numeryczną $URL).

2. Chciałbym uniknąć dodawania ścieżek do każdego adresu URL. Które metody nadadzą się najlepiej - dla hostingów z mod_rewrite i bez niego? Jak do tego podejść? Dlaczego chcę tego uniknąć? Już wyjaśniam:

Dużo adresów URL znajduje się także w szablonach. Konieczność wstawienia ścieżki może stanowić duże utrudnienie dla twórców skórek, gdyż im prostsza składnia i poziom skomplikowania kodu, tym więcej chęci, aby się za coś zabrać.<a href="{URL_PATH}cats/2">{lang.files}</a>Czy w szablonach w ogóle powinny być URL-e?

?foo=1&bar=2 zamieniony na foo/1/bar/2/ nie jest żadną sensowną zmianą. "Przyjazne" linki to /telefony/nokia/n900/. Wyszukiwarki bez problemu indeksują URLe z parametrami GET.

Co do URLi w szablonach - Django ma odpowiedni tag szablonów generujący URL dla podanego widoku z aplikacji na bazie określonego dla projektu mapowania URL - widok aplikacji. Nie trzeba dzięki temu aktualizować szablonów, gdy zmieni się mapowanie w urls.py ;) Tyle że nie jest zbyt często stosowane - bo nie ma takiej potrzeby. Wali się zwykłymi linkami i tyle.

Ogólnie nie kombinuj. Siłowe wykorzystywanie foo/1/bar/2/ zamiast ?foo=1&bar=2 to strata czasu. Obsługa badziewnych hostingów tym bardziej. Poważnemu pracodawcy to zwisa (że zrobiłeś "skrypta dla dzieci na yoyo.pl"), a babranie się w "zaawansowane" rozwiązania dla skryptu do zastosowań na podrzędnych serwerach przez dzieci (PHP-Fusion) na mało przydatne stronki - jeszcze większa. Albo odpuść przepisywanie, albo serwery, które go nie obsługują.



oj a z tym łatwym ideksowaniem parametrów get mylisz się Riklaunim, bo niestety adres ciężko dodaje się do map strony, gdyż błąd powodują w pliku xml znaki "&"...


oj a z tym łatwym ideksowaniem parametrów get mylisz się Riklaunim, bo niestety adres ciężko dodaje się do map strony, gdyż błąd powodują w pliku xml znaki "&"...
&amp; i po krzyku.

pająki wyszukiwarek nie są jakimiś ograniczonymi skrypcikami, a jednym z bardziej zaawansowanego oprogramowania. Nie straszne i parametry GET, czy bardzo duże serwisy.
Użytkownik Riklaunim edytował ten post 31 październik 2009, 16:05
Zgadzam się - wyszukiwarki radzą sobie dobrze z parametrami GET.

Nie robi mi to wielkiej różnicy. Łatwiej znaleźć poszukiwaną stronę w Google niż wpisywać URL na chybił trafił. Problemem są systemy statystyk, które ucinają wszystko po ? w zakładkach typu "witryny odsyłające".

Więc po co stosować "przyjazne URL"? Aby obciążyć serwer i zadać więcej trudu programistom? Stwierdzenie, że strzelam sobie w stopę, jest trafne. Dzisiaj obsługę krótkich linków traktuje się jako 1 z najważniejszych funkcji skryptów.

1. Lepsza pozycja w wyszukiwarkach - 30% - Google radzi sobie dobrze ze zwykłymi
2. Systemy statystyk pomijają wszystko po ? - 50% - GA i Stat24 pomijają
3. User wpisze adres z palca - 5% - może zapamiętać też zwykły, choć "nice" ma łatwiejszą składnię
4. Łatwiej przekazać innym adres - 5% - fakt, że łatwiej, jeśli dojdzie do takiej sytuacji
5. Ładniej wygląda - 10% - czasami to robi różnicę, ale aż tak wielką?

Implementację krótkich URL-i wymusił rynek (tu: darmowych!) skryptów :)

Zastanawiam się, czy pomysł z wykorzystaniem systemu plików wypali. Przykład: domain.com/go/pms/outbox
go - stała część URL, aby nie śmiecić w głównym folderze
pms - folder
outbox - folder zawierający index.php, gdyż plik "outbox" w pms miałby typ text/plain, a PHP nie wykona się *

Ewentualnie sposób z /index.php/pms/outbox - też można wpisać ścieżkę w <base> i po problemie - ale PATH_INFO jest wyłączony na hostingach całkiem do ... chociaż może nie ma sensu ich wspierać, bo to raczej margines. B)

* Typ dokumentu można wymusić, ale raczej nie da się włączyć interpretera PHP

EDIT: Gdy umieszczę w <base> pełny URL wraz z index.php, nie załadują się skrypty, grafika, CSS... Podobnie, gdy katalogi będą umieszczane w osobnym folderze w opisanym wyżej sposobie z systemem plików. Tworzenie folderów w głównym katalogu to ryzyko, bo może dojść do konfliktu. Chyba nie obędzie się bez dodawania prefiksów do każdego URL. Muszę przemyśleć jeszcze kwestię przyjaznych URL.
Użytkownik Ferrari edytował ten post 31 październik 2009, 20:27
Jako że używam Django, które stosuje tego typu system URLi "domyślnie" to powiem ci że to średnie rozwiązanie do amatorów, którzy nie przywykli do stosowania bezwzględnych wewnętrznych URLi, jak i musiałbyś obsługiwać umieszczanie skryptu w podkatalogu (a nie tylko prosto w domenie/subdomenie) - czyli "doklejanie" podkatalogów jako prefiksu wszystkich wewnętrznych bezwzględnych URLi ;)

Tworząc skrypt dla amatorów nie jest ważna piękność URLi, czy quasi-optymalizacje (strona z 1-5000 UU dziennie tego nie wymaga ponad zwykłe poprawne wykonanie). Ma to wyglądać ładnie, profesjonalnie jak Wordpress (i zachęcać webdesignerów do tworzenia świetnych skórek), czy też półkę wyżej idąc - dawać platformę do rozbudowy o nowe funkcjonalności i moduły jak Drupal (CMF). I nie jest to robota dla jednej osoby (poza może wersją "pierwszą").

Zapytałem użytkowników - 4/6 chce przyjaznych URL, 1 nie wie, 1 nie oczekuje. Większość woli przyjazne URL:twoj.adres.pl/pms/view/50 [3 głosy] twoj.adres.pl/index.php/pms/view/50 [2 głosy]Natomiast NIE lubią w szczególności:twoj.adres.pl/?page=pms/view/50 [5 głosów] twoj.adres.pl/?co=pms&act=view&id=50 [3 głosy] twoj.adres.pl/?pms/view/50 [2 głosy] twoj.adres.pl/index.php/pms/view/50 [2 głosy]5 osób ma dostęp do mod_rewrite i PATH_INFO. 4 ankietowanych twierdzi, że powinna być możliwość powrotu do starej formy URL-i. Dochodzi jeszcze kwestia kompatybilności.

Celowo nie zaprezentowałem URL-i typu /file/mozilla_firefox_3 w przykładach, aby ankietowani zwrócili uwagę na formę.

Zdecydowałem zaimplementować krótkie URL-e. Podniesie to rangę produktu.

Zatem mam 2 możliwości:

1. Stworzyć funkcję generującą URL-e.

Oto funkcja, która generuje URL na podstawie ustawień:function url($x, $query=null, $path=null) { switch(URL_MODE) { case 1: return $path . $x . ($query ? '?'.$query : ''); break; case 2: return $path . 'index.php/' . $x . ($query ? '?'.$query : ''); break; default: return $path . '?' . $x . ($query ? '&'.$query : ''); } }Natomiast tak tworzymy URL-e w modułach:$url = url('pms/inbox', 'sortBy=name');W .htaccess wystarczy wpisać:RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.+) index.php?path=$1 [L,QSA]
Własności i wymagania:
1) wszystkie adresy trzeba generować za pomocą tej funkcji
2) zrywamy z kompatybilnością wsteczną
3) aby jednak zachować kompatybilność, można na samym początku konwertować stare adresy na nowe
4) dowolna ilość zagłębień: $URL[0], $URL[1], ..., $URL[n]
5) nazwa modułu jest w $URL[0], a reszta (np. ID, nazwa akcji) - zależy od modułu
6) hierarchiczna budowa URL - łatwiej zachować kontrolę

2. Generować URL-e indywidualnie

W każdym module, w którym chcemy mieć przyjazne URL, generujemy je tak:$url = (NICE_URL) ? 'pms/inbox' : '?co=pms&folder=inbox';
W .htaccess potrzeba więcej reguł, aby skonwertować URL do postaci parametrycznej (kolejność może być inna):RewriteRule ^([a-z]+)([0-9]+)$ index.php?co=$1&id=$2 [L,QSA] RewriteRule ^([0-9]+)$ index.php?d=$1 [L,QSA] RewriteRule ^([a-z0-9]+)$ index.php?co=$1 [L,QSA] RewriteRule ^([a-z]+)-([a-z]+)([0-9]+)$ index.php?co=$1&act=$2&id=$3 [L,QSA] RewriteRule ^([a-z]+)-([a-z]+)$ index.php?co=$1&act=$2 [L,QSA]Wyrażenia napisałem dawno temu. W kolejności interpretujemy linki, które prowadzą do:
1) elementu o określonym ID (co + id)
2) numeru kategorii (d)
3) modułu - bez ID bądź określonej akcji (co)
4) elementu o określonym ID, ale o określonej akcji (co + act + id)
5) modułu o określonej akcji (co + act)

Oczywiście brakuje jeszcze w wyrażeniach regularnych miejsca na tytuł artykułu / strony / czego bądź, ale z tym nie będzie problemu. Po otrzymaniu żądania interpretujemy elementy jak wcześniej. Wymagania i cechy:
1) ID elementu musi znaleźć się koniecznie w parametrze `act`, zaś akcja w `id`
2) maksymalnym poziomem zagłębienia jest /moduł/akcja, resztę trzeba przekazać w parametrach po znaku ?
3) zachowana kompatybilność wsteczna
4) nie trzeba tworzyć dziwnych URL-i dla słabych hostingów: /?page=pms/inbox, /?pms/inbox...
5) brak centralnego nadzoru nad URL-ami
6) większe bezpieczeństwo - wiadomo, że numeryczny ID zawsze jest w zmiennej $_GET['id']
7) nie wszystkie URL-e muszą być "przyjazne" - to zależy od modułu / rozszerzenia

Mam nadzieję, że wyjaśniłem wszystko szczegółowo :) Wybór ciężki. Z jednej strony można uczynić skrypt bardziej elastycznym, atrakcyjnym i przyjaznym dla SEO, z drugiej - kompatybilność i [możliwe] problemy z uruchomieniem mod_rewrite na różnych serwerach (wiem, jak to jest - nie każdy zaglądnie do działu pomocy swojego hostingu).

6 osób to możesz sobie statystycznie wsadzić ;) i pewnie jeszcze z rok będziesz roztrząsał jak z przepisywania linków zrobić następny rok kodowania bez większego sensu i po tym 2 lata optymalizowania z 0,000011s na 0,000010s. Zazwyczaj przepisywanie linków w popularnych CMSach jest opcjonalne i można to po prostu włączać i wyłączać.

Napisz CMSa, który działa, dobrze wygląda i jest dostępny także/głównie w anglojęzycznej wersji. Zainteresują topowych bloggerów (anglojęzycznych) żeby przyjrzeli się temu i napisali na swoich blogach recenzje - wtedy zyskasz duży feedback i będziesz wiedział co dalej robić + może jakiś chętnych do pomocy... W tym roku pojawiło się kilka - kilkanaście nowoczesnych systemów CMS, które dostały dobre recenzje, a liczba użytkowników szybko rośnie. Stworzenie i udana premiera pierwszych wersji zabrała im kilka miesięcy lub mniej, a też mogą mieć ładne linki, bez roztrząsania tego (bo nie ma czego roztrząsać). I tego samego będą wymagać twoi przyszli pracodawcy - tworzenia projektów w określonym (krótkim) terminie bez zbędnych "optymalizacji",rozbudowywania kodu i wynajdywania koła na nowo :D

A spróbuj podejrzeć, jak to zrobili w Smarty ;)

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • nvm.keep.pl

  • Sitedesign by AltusUmbrae.