Licznik w PHP

Tym razem opiszę jeden z najprostszych skryptów PHP, a zarazem najpowszechniej używanych. Mianowicie prosty licznik, ale jednak odporny na odświeżanie.

Odporność na odświeżanie można zrealizować na trzy sposoby: sprawdzając nagłówek HTTP_REFERER, przy pomocy ciasteczek oraz korzystając z sesji. Użycie dwóch sposobów (tzn. ciasteczek i nagłówka) charakteryzuje się wystarczającą odpornością.

O ciasteczkach krótko

Czym są ciasteczka (ang. cookies)? Ciasteczka są plikami tekstowymi, przechowywanymi przez przeglądarki i zawierającymi informacje, z których korzystają serwisy internetowe. Mało kto je zauważa, ale w każdej przeglądarce jest ich pełno. Zazwyczaj również słyszy się, że są niebezpieczne. Jest to bzdurą, ponieważ w ciasteczku nie da się zapisać niczego co mogłoby być niebezpieczne. Jednak jeśli ktoś, używając przeglądarki internetowej, sprawdzał na przykład pocztę i zapomniał się wylogować, to (jeśli przeglądarka nie została zrestartowana) istnieje możliwość podejrzenia cudzej poczty przez osoby, które korzystają z tego samego komputera i z tej samej przeglądarki. Ich niebezpieczeństwo wynika z bezmyślności użytkowników.

Nieco kodu

Skrypt licznika, który jest odporny na przeładowania, to w rzeczywistości dwa bloki kodu liczące po kilka linijek każdy. Pierwszym blokiem jest blok ustawiający ciasteczko, sprawdzający zmienną HTTP_REFERER i ewentualnie dopisujący ilość odwiedzin do pliku. Drugi blok wyświetla tylko liczbę, która jest ilością odwiedzin.

Przed rozpoczęciem działania należy stworzyć plik, w którym będą odnotowywane odwiedziny. Niech ten plik nazywa się licznik.txt. Jego zawartość początkowa to:

0;

Aby wszystko działało poprawnie, prawa dostępu do tego pliku powinny być 666 (rw-rw-rw-), czyli powinien być możliwy odczyt i zapis dla wszystkich.

Pierwszy blok:

<?php
	if((!isset($_COOKIE['licznikowe-ciacho'])) && (!strstr($_SERVER['HTTP_REFERER'], "strona.pl"))) {
		$plik = fopen("licznik.txt", "r");
		$tekst = fread($plik, filesize("licznik.txt"));
		$dane = explode(";", $tekst);
		fclose($plik);
		$plik = fopen("licznik.txt", "w");
		flock($plik, 2);
		$dane[0]++;
		fwrite($plik, "$dane[0];", 15);
		flock($plik, 3);
		fclose($plik);
		setcookie("licznikowe-ciacho", "zliczono", 0);
	}
	else {
		$plik = fopen("licznik.txt", "r");
		$tekst = fread($plik, filesize("licznik.txt"));
		$dane = explode(";", $tekst);
	}

?>

Jak widać, ten blok składa się tylko z kilku instrukcji, które zostaną wykonane zależnie od warunku. Warunek spełni się jeśli przeglądarka nie wysłała skryptowi ciasteczka (ciasteczko nie ustawione) oraz jeśli w zmiennej $_SERVER['HTTP_REFERER'] nie znajduje się adres naszej strony. Adresem strony w przykładzie jest strona.pl, ale oczywiście należy to zamienić na odpowiedni adres. Ważne jest, żeby nie używać w tym miejscu przedrostka www.. W ostatniej linijce bloku spełnionego warunku znajduje się instrukcja tworzenia ciasteczka. Pierwszym parametrem funkcji setcookie() jest nazwa ciasteczka, drugim zawartość tego ciasteczka, a trzecim okres jego ważności. W tym przykładzie jest to zero, co oznacza, że ciasteczko zostanie usunięte w momencie wyłączenia przeglądarki, ale równie dobrze można ustawić mu ważność na dwa dni (zamiast zera należy wpisać time()+172800), czy na dwa tygodnie (time()+1209600).

Niespełnienie warunku spowoduje jedynie odczytanie ilości odwiedzin, bez ich inkrementacji.

Pierwszy blok powinien być umieszczony w dokumencie, w miejscu, w którym nie zostały jeszcze wysłane wszystkie nagłówki, czyli w miejscu, w którym do przeglądarki nie zostały wysłane znaki CR-LF CR-LF (dwa znaki nowej linii). W praktyce, takim miejscem jest zawsze początek dokumentu, a właściwie skryptu PHP. Taki wymóg spowodowany jest tym, że ciasteczko trafia do przeglądarki właśnie jako nagłówek.

Drugi blok:

<p>Jesteś <?php echo($dane[0]); ?> gościem na mojej stronie.</p>

Powyższy zapis jest oczywiście przykładowy. Treść może zostać zmieniona, ale najważniejszą częścią, która musi pozostać jest: <php echo($dane[0]); ?>.