Artykuł

sxc.hu sxc.hu
lut 27 2010
0

Przyjazne linki z PHP i MySQL oraz przekierowanie 301

W ostatnim czasie postanowiłem utworzyć na stronie tzw. przyjazne linki (z ang. nice urls). Efekt tej operacji widoczny jest w tej chwili w pasku adresu. O ile utworzenie przyjaznych linków dla nowej, świeżo budowanej strony nie nastręcza wielu problemów, o tyle w przypadku strony, która już została zakorzeniona w Internecie jest to nieco większe wyzwanie. Oprócz obsłużenia nowych linków w skrypcie strony, musimy zadbać o odpowiednie przekierowania dla linków już zaindeksowanych przez wyszukiwarki. Można tutaj skorzystać z .htaccess (przy założeniu, że na serwerze został zainstalowany serwer Apache), ale rozwiązanie to bywa męczące i nieefektywne. Dlatego najlepiej, przekierować cały ruch na plik główny czyli np. index.php i tam dokonać obsługi konkretnych akcji. O tym jak tego dokonać w języku PHP opowiem Wam w dzisiejszym artykule. Ponadto, pokaże jak można wykorzystać bazę danych MySQL do tworzenia linków zawierających tytuły artykułów.

Dlaczego warto stosować przyjazne linki?

Pierwszą i niezaprzeczalną zaletą przyjaznych linków jest niewątpliwie ich bardziej przyjazna budowa. Link postaci:

http://www.domena.tld/index.php?cat=test&id=1

Jest zdecydowanie bardziej zawikłany niż np. taki link:

http://www.domena.tld/kategoria/test/1/

Przyjazne linki są również bardziej semantyczne ponieważ często zawierają wewnątrz słowa kluczowe użyte na określonej podstronie. Ponadto, umożliwiają odtworzenie w wyszukiwarce strony, jako sterty uporządkowanych katalogów. Zwróćmy uwagę na następujące linki:

/artykuly/przyjazne-linki-z-php-i-mysql-oraz-przekierowanie-301/
/kategoria/internet/
/kategoria/internet/2/
/zrodla/funkcja-kwadratowa/

Powyższe odnośniki, prezentują kilka charakterystycznych elementów dla strony. Każdy przedstawia inny katalog/dział witryny. Pierwszy URL, jest odnośnikiem do artykułu. Wykorzystaliśmy tutaj pobrane z bazy danych informacje - tytuł artykułu. Dzięki temu, URL zawiera słowa kluczowe użyte w tekście i lepiej się pozycjonuje. Drugi przykład, to odnośnik do kategorii. Mamy tutaj katalog kategoria, a następnie tytuł określonej kategorii. Trzeci URL jest podobny do drugiego, z tym że zawarty tutaj został również numer strony wybranej kategorii. Ostatni URL, to kod źródłowy funkcji kwadratowej napisanej w Javie. Również w tym przypadku, wykorzystaliśmy bazę danych do pobrania nazwy wybranego źródła, ale umieściliśmy je w innym folderze.

Wykorzystanie przyjaznych linków, może również zwiększyć bezpieczeństwo naszej strony, ponieważ potencjalna osoba atakująca nie zna struktury naszej witryny, nie wie jakie parametry są używane i nie wie przede wszystkim jaki język został użyty do budowy serwisu.

Z przyjaznych linków korzysta wiele popularnych serwisów, systemów, blogów np. Wordpress. Jest to w dniu dzisiejszym, po prostu standard.

Przygotowanie podłoża - plik .htaccess

Celem tego artykułu, było między innymi ograniczenie manewrów tworzenia przyjaznych linków za pomocą .htaccess i tak też się dzieje. Ale pewne reguły powinniśmy jednak tam umieścić. Dlatego stwórzmy coś takiego:

RewriteEngine on
RewriteRule ^.+(obrazy/.+)$ $1 [L]
RewriteRule ^.+(skrypty/.+)$ $1 [L]
RewriteRule ^.+(style.css)$ $1 [L]
RewriteRule ^.+(rss.xml)$ $1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?$1 [L]

Przeanalizujmy powyższy kod. W pierwszej linii, uruchamiamy mechanizm przepisywania URL (dokładniej mówiąc moduł mod_rewrite, w pliku httpd.conf - musi on być odkomentowany. Jeśli nie posiadamy dostępu do pliku konfiguracyjnego serwera, należy sprawdzić dane konta, lub skontaktować się z administratorem.). Następnie, ustawiamy reguły dla elementów statycznych, np. obrazków, plików CSS czy JS, które po zaaplikowaniu reguł mogły by się nie wyświetlać prawidłowo (chyba, że do każdego zasobu podajemy pełny URL, aczkolwiek utrudnia to testowanie na różnych serwerach). Przykłady tej operacji obejmują linie 2-5. Linie 6-8, są odpowiedzialne za przekazywanie całej reszty napływających żądań na plik index.php. W linii 8 widoczne jest wyrażenie regularne, które odpowiada za to zdarzenie.

Nie jest to artykuł stricte na temat .htaccess czy wyrażeń regularnych, ale pewne rzeczy warto wyjaśnić dla formalności. $1 oznacza dopasowany element, z pierwszej grupy określonej we wzorcu. [L] zapisane na końcu linii oznacza, że jeśli żądanie pasuje do danej reguły to żadna z kolejnych reguł dla tego określonego zapytania nie ma być wykonywana. Innymi słowy L = LAST = Ostatni.

Baza danych wspomagająca przyjazne linki

Załóżmy, że mamy stronę na której co jakiś czas dodajemy nowy artykuł. Każdy tekst ma swój unikalny id, tytuł oraz treść. My, utworzymy dodatkowo pole przechowujące przyjazny tytuł artykułu. Dzięki temu, będziemy taki string generować tylko raz przy dodawaniu, lub ewentualnie więcej razy przy edycji tekstu. Na nasze potrzeby, wystarczy taka tabela MySQL:

CREATE TABLE Texts (
  textid INTEGER NOT NULL AUTO_INCREMENT,
  title VARCHAR(150) NOT NULL,
  url VARCHAR(150) NOT NULL,
  content TEXT NOT NULL,
  PRIMARY KEY(textid))

Utworzyliśmy zatem, prostą tabelę Texts. Posiada ona wcześniej wymienione pola. Wartość pola textid, jest automatycznie generowana przez bazę danych. Wartości kolumn title oraz content definiuje użytkownik. Ostatnie pole: url wypełniane jest przez skrypt dodający lub edytujący tekst w bazie danych.

Jeśli jesteśmy już w bazie danych, warto napisać zapytania typu SELECT pobierające treść artykułu na podstawie URLa wczytanego z pasku adresu:

SELECT * FROM Texts WHERE url="jakis-przyjazny-url"

Oczywiście powinniśmy obsłużyć zdarzenie, w którym żądany artykuł nie zostanie odnaleziony, lub kiedy ktoś spróbuje wprowadzić jakieś złe dane.

Jeśli strona istnieje jakiś czas, warto również posiadać funkcję, która dla żądanego id będzie zwracać tytuł tekstu. Przykładowo:

SELECT url FROM Texts WHERE textid=x

Oczywiście x zastępujemy określonym numerkiem id.

Tworzenie przyjaznych linków z poziomu PHP

Jak już wspomniałem wcześniej, każdy tekst powinien posiadać swój przyjazny url i aby nie powtarzać wielokrotnie procesu jego tworzenia, warto zapisać go w bazie danych. Sam zapis w bazie danych odbywać będzie się w momencie dodawania artykułu do bazy lub jego edycji.

W oparciu o temat z forum Pozycjonowanie i Optymalizacja napisałem prostą funkcję tworzącą przyjazne linki, niezależnie od użytego kodowania znaków:

<?php
function MakeFriendlyUrl($sString)
{
	$asCharacters = Array(
	   //WIN
		"\xb9" => "a", "\xa5" => "A", "\xe6" => "c", "\xc6" => "C",
		"\xea" => "e", "\xca" => "E", "\xb3" => "l", "\xa3" => "L",
		"\xf3" => "o", "\xd3" => "O", "\x9c" => "s", "\x8c" => "S",
		"\x9f" => "z", "\xaf" => "Z", "\xbf" => "z", "\xac" => "Z",
		"\xf1" => "n", "\xd1" => "N",
	   //UTF
		"\xc4\x85" => "a", "\xc4\x84" => "A", "\xc4\x87" => "c", "\xc4\x86" => "C",
		"\xc4\x99" => "e", "\xc4\x98" => "E", "\xc5\x82" => "l", "\xc5\x81" => "L",
		"\xc3\xb3" => "o", "\xc3\x93" => "O", "\xc5\x9b" => "s", "\xc5\x9a" => "S",
		"\xc5\xbc" => "z", "\xc5\xbb" => "Z", "\xc5\xba" => "z", "\xc5\xb9" => "Z",
		"\xc5\x84" => "n", "\xc5\x83" => "N",
	   //ISO
		"\xb1" => "a", "\xa1" => "A", "\xe6" => "c", "\xc6" => "C",
		"\xea" => "e", "\xca" => "E", "\xb3" => "l", "\xa3" => "L",
		"\xf3" => "o", "\xd3" => "O", "\xb6" => "s", "\xa6" => "S",
		"\xbc" => "z", "\xac" => "Z", "\xbf" => "z", "\xaf" => "Z",
		"\xf1" => "n", "\xd1" => "N");		
	$sString = strtr($sString, $asCharacters);
	$sString = strtr($sString, 'ˇ¦¬±¶Ľ','ASZasz');
	$sString = preg_replace("'[[:punct:][:space:]]'",'-',$sString);
	$sString = strtolower($sString);
	$sChar = '-';
	$nRepeats = 1;
	$sString = preg_replace_callback('#(['.$sChar.'])\1{'.$nRepeats.',}#', create_function('$a', 'return substr($a[0], 0,'.$nRepeats.');'), $sString);
	return $sString;	    
}	 
?>

Funkcja tworzy URLe w postaci: slowa-bez-polskich-znakow. W skrócie, litery duże zmieniane są na małe, polskie znaki zamieniane są na ich odpowiedniki bez ogonków (funkcja korzysta z trzech różnych standardów kodowań), usuwane są wszystkie niepożądane znaki, a odstępy zastępowane są przez znaki -, dzięki czemu URL jest bardziej przyjazny dla wyszukiwarek.

Przetwarzanie URL z poziomu PHP

Napisałem już o .htaccess, napisałem co nieco o bazie danych, a także o tworzeniu samych przyjaznych URL. Czas na ostatni etap tej ścieżki czyli kod PHP obsługujący napływające żądania. Zgodnie z zapisami umieszczonymi w pliku .htaccess, przekierowujemy wszystkie przychodzące do strony żądania na plik index.php. W tym momencie, powinniśmy zadać sobie pytanie, jak chcemy uporządkować naszą witrynę. Dla przykładu, na moim blogu możemy znaleźć linki typu:

/artykuly/przyjazne-linki-z-php-i-mysql-oraz-przekierowanie-301/
/kategoria/programowanie/
/zrodla/flaga/

Taki link możemy rozpracować w sposób następujący:

domena/grupa elementów/element/

Domena zawsze jest w tym przypadku stała, a z przytoczonych listingów, możemy wyróżnić trzy grupy elementów: artykuly, kategorie oraz zrodla. Dlatego najpierw powinniśmy rozpracować nasz URL na elementy. Jeśli plik index.php, znajduje się w głównym katalogu serwera (tak jest raczej standardowo), to możemy tego dokonać w następujący sposób:

$sUrl = strip_tags($_SERVER['REQUEST_URI']);
$asUrlElements = explode('/', $sUrl);

A ten strip_tags to po to, jeśli jakiś przebiegły Internauta miał złowrogie zamiary wobec naszej strony. Uzyskaliśmy zatem, tablicę elementów. Ponieważ element $asUrlElements[0] zawsze przechowywać będzie typ określonej grupy elementów to możemy zrobić sobie tutaj jakiegoś fajnego switcha:

switch($asUrlElements[0])
{
	case 'artykuly':
		ArticlesCmd($asUrlElements[1]);
		break;
	case 'kategoria':
		CategoryCmd($asUrlElements[1]);
		break;
	case 'zrodla':
		SourcesCmd($asUrlElements[1]);
		break
	// itd.
}

W ten sprytny sposób poradziliśmy sobie z podstawową obsługą żądań. Oczywiście powinniśmy zadbać o obsługę zdarzenia domyślnego - wyświetlimy wtedy stronę główną, albo też zdarzenie strony z błędem 404. Do każdej funkcji, przekazaliśmy również kolejny element z łańcucha URL, który zawiera zazwyczaj identyfikator konkretnego elementu.

Kolejnym krokiem, jest obsługa konkretnych elementów poprzez funkcje przeznaczone do tego celu. I tak np. w funkcji dla artykułów, przekazaliśmy drugi parametr z naszego URL, będący przyjaznym tytułem tekstu. Musimy teraz wykonać zapytanie, pobierające dane dla tego tytułu (wykorzystując jedno z zapytań napisanych wcześniej w tym artykule), a następnie wyświetlić je. I to właściwie tyle w temacie.

301 dla witryn ze stażem

Na koniec mały suplement dla stron, które już istnieją w sieci. W przypadku takich witryn, powinniśmy zadbać o przekierowanie wejść ze starych linków, na nowe linki. Dlatego, w kodzie strony najpierw obsługujemy stare żądania i wykonujemy dla nich przekierowania 301, a dopiero potem, rozpatrujemy URL pod kątem przyjaznych linków. Jeśli spojrzymy na problem pod kątem instrukcji sterującej if, przyjazne linki to nasz else, a stare żądania to wszystkie pozostałe if oraz else if. Rozważmy przykład w postaci linku:

http://www.altcontroldelete.pl?index.php?id=1

Musimy odebrać takie, żądanie a następnie wykonać odpowiednie przekierowanie. Przyda tutaj się nam zapytanie napisane wcześniej, które pobiera z bazy danych przyjazny tytuł artykułu, na podstawie jego id:

$sArticleLink = GetArticleLink($_GET['id']);
if(false != $sArticleLink)
{
	Header( 'HTTP/1.1 301 Moved Permanently' );
	Header( 'Location: /artykuly/'.$sArticleLink.'/');					
}

Rozważmy powyższy kod. Funkcja GetArticleLink, posiada jeden parametr będący id artykułu. Na tej podstawie, wyszykuje w bazie danych przyjazny tytuł tego artykułu. Jeśli znajdzie go, to go zwraca i wykonuje stałe przekierowanie 301 na uzyskany dzięki bazie danych link (linie 4-5). Jeśli nie, to zwraca wartość false.

Powyższe przekierowanie, warto stosować w początkowym okresie zmiany URLi. Jeśli po jakimś czasie, wszystkie stare URLe, zostaną wyplewione z wyszukiwarek, możemy również wyrzucić powyższe przekierowania. Zawsze warto również posiadać jakąś przyjemną stronę dla błędów 404.

Podsumowanie

Dzisiejszy artykuł, miał w zarysach ukazać sposób w jaki można utworzyć przyjazne linki zarówno dla nowej jak i istniejącej witryny. Przykładowe listingi napisane w sposób strukturalny, miały jedynie charakter poglądowy, ukazujący podejście do tematu. W razie jakichkolwiek pytań, zapraszam do komentarzy.

Data ostatniej modyfikacji: 11.02.2014, 11:36.

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus