Sprawiamy, że nasza funkcjonalność sprawdzania ilu użytkowników jest na stronie działa w pełni poprawnie. Do dzieła.
Poprzednio stanęliśmy na tym:
<?php
class Session
{
//(...)
public static function sessions5Minutes(){
$session_path = session_save_path();
$handle = opendir($session_path);
$sessions = 0;
while (($file = readdir($handle)) != FALSE) {
if(in_array($file, ['.', '..']))
continue;
if(!preg_match("/^sess/", $file))
continue;
$file_path = "{$session_path}/{$file}";
$last_access = date("Y-m-d H:i:s", fileatime($file_path));
$now = date("Y-m-d H:i:s", strtotime("-5 minutes"));
if($now <= $last_access)
$sessions++;
}
return $sessions;
}
}
Session::start();
echo Session::sessions5Minutes();
//1
I możliwe, że jeżeli otworzymy w nowej przeglądarce nasze okno utworzony zostanie plik sesji i jego data ostatniego accessu będzie się mieścić w minus 5 minut i liczba się nam o 1 zwiększy.
Możliwe też, że mamy tam już sesję istniejącą zaś dane dotyczące ostatniego accessu do tego już istniejącego pliku są w cache jako 'stale’.
Rozwiązanie:
<?php
class Session
{
//(...)
public static function sessions5Minutes(){
$session_path = session_save_path();
$handle = opendir($session_path);
$sessions = 0;
clearstatcache();
while (($file = readdir($handle)) != FALSE) {
if(in_array($file, ['.', '..']))
continue;
if(!preg_match("/^sess/", $file))
continue;
$file_path = "{$session_path}/{$file}";
$last_access = date("Y-m-d H:i:s", fileatime($file_path));
$now = date("Y-m-d H:i:s", strtotime("-5 minutes"));
if($now <= $last_access)
$sessions++;
}
return $sessions;
}
}
Ok, czyścimy kesz, nowe dane mamy. Co jednak jeśli użytkownik nadal jest na stronie, odświeżył 5 sekund temu, ale po prostu data ostatniego odczytu z pliku sesyjnego jest starsza niż te 5 minut bo przez te 5 minut nic do sesji nie było zapisywane ani z niej odczytywane?
Cóż, i to można naprawić:
<?php
class Session
{
//(...)
public static function sessions5Minutes(){
$session_path = session_save_path();
$handle = opendir($session_path);
$sessions = 0;
clearstatcache();
static::set("_cache", (string)time());
while (($file = readdir($handle)) != FALSE) {
if(in_array($file, ['.', '..']))
continue;
if(!preg_match("/^sess/", $file))
continue;
$file_path = "{$session_path}/{$file}";
$last_access = date("Y-m-d H:i:s", fileatime($file_path));
$now = date("Y-m-d H:i:s", strtotime("-5 minutes"));
if($now <= $last_access)
$sessions++;
}
return $sessions;
}
}
Zapisujemy coś do sesji, zatem wymuszamy access do pliku sesyjnego (samo session_create w żaden sposób tego nie aktualizuje, jeżeli sesja już jest). Na razie jednak robimy to tylko na tej stronie, która podlicza aktywnych użytkowników.
Czytaj – zobaczysz ilu użytkowników gapi się na licznik aktywnych użytkowników. Nie – ilu na całej twojej stronie w tym czy innym miejscu przebywa.
Jeszcze nie znamy konceptu middleware, którego będziemy używać w naszym projekcie MVC, więc na razie proponuję takie rozwiązanie:
<?php
class Session
{
//(...)
public static function onEveryRequestMiddleware(){
static::start();
static::set("_cache", (string)time());
}
}
Session::onEveryRequestMiddleware();
echo Session::sessions5Minutes();
//3
Jeżeli tę metodę wywołamy na każdej naszej stronie symulując coś takiego jak middleware, to każde odświeżenie jakiejkolwiek strony wiąże się z utworzeniem sesji jeśli ta nie istnieje i próbą dostępu do jej pliku sesyjnego, dzięki czemu możemy mieć idealnie działający mechanizm pokazywania ilości użytkowników online.