6 commenti my script, mysql, php

Per conoscere chi sono gli utenti on line in un determinato momento la logica da seguire è semplice: bisognerà inserire in una tabella MySql dedicata (online_users) una chiave che idendifica in modo univoco l'utente (key_user) e, congiuntamente, salvare il timestamp attuale (data_last_log).

 

Navigando all'interno del sito andremo ad aggiornare il timestamp salvato in modo da conoscere sempre la data e l'ora dell'ultima operazione effettuata da quello specifico utente (identificandolo univocamente con la sua key_user). 

 

Fissando un intervallo convenzionale, poniamo 10 minuti, andremo ad eliminare tutti gli utenti "scaduti". In pratica, si ipotizza che l'utente essendo inattivo per un periodo superiore a 10 minuti è uscito dal sito, cioè non è più online. 

 

A questo punto per conoscere il numero di utenti online basterà contare i record presenti all'interno della tabella (gli scaduti sono eliminati); se si vuo sapere "chi sono" dovremo analizzare la key salvata.

 

La tabella MySql avrà una struttura di questo tipo:

CREATE TABLE IF NOT EXISTS `online_users` (
  `id_log` int(11) NOT NULL AUTO_INCREMENT,
  `key_user` varchar(255) NOT NULL,
  `data_last_log` datetime NOT NULL,
  PRIMARY KEY (`id_log`)
)

 

Utilizzare l'IP come Key univoca per identificare l'utente

Se siamo senza di un sistem di login la tracciabilità dell'utente si baserà tradizionalmente in base al suo IP (presente all'interno della variabile $_SERVER['REMOTE_ADDR']). Infatti, avendo ciascun utente un proprio ip questo ci può fornire un'identificazione univoca dell'utente.

 

Ecco di seguito la classe Onlineusers per gestire tutte le operazioni:

<?php
Class OnlineUsers{
	protected $key;
	protected $minute_finish = 10;
	
	public function __construct(){
		$this->key = $this->get_key(); // otteniamo la key
		$this->clear_table(); // eliminiamo gli utenti "scaduti"
		if(!$this->isset_key()){ // non esiste la key
			$this->insert_key(); // allora la inseriamo
			}
		else{
			$this->update_data_key(); // altrimenti aggiorniamo il timestamp
			}
		}
		
	protected function isset_key(){
		$query = "SELECT * FROM online_users WHERE key_user='" .mysql_real_escape_string($this->key). "'";
		$result = mysql_query($query) or die(mysql_error());
		if(mysql_num_rows($result)>=1){
			return TRUE;
			}
		return FALSE;
		}
	
	protected function update_data_key(){
		$query = "UPDATE online_users SET data_last_log=NOW() WHERE key_user='" . mysql_real_escape_string($this->key) . "'";
		$result = mysql_query($query) or die(mysql_error());
		return TRUE;
		}
	
	protected function insert_key(){
		$query = "INSERT INTO online_users SET key_user='" . mysql_real_escape_string($this->key) . "', data_last_log=NOW()";
		$result = mysql_query($query) or die(mysql_error());
		return mysql_insert_id();
		}
	
	protected function clear_table(){
		$query = "DELETE FROM online_users WHERE data_last_log<=DATE_SUB( NOW() , INTERVAL ". intval($this->minute_finish) ." MINUTE )";
		$result = mysql_query($query) or die(mysql_error());
		return TRUE;
		}
	
	protected function get_key(){
		$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'undefined';
		return $ip;
		}
	
	public function get_count_online(){
		$query = "SELECT COUNT(*) AS num_user FROM online_users ORDER BY data_last_log ASC";
		$result = mysql_query($query) or die(mysql_error());
		$fetch = mysql_fetch_array($result);
		return $fetch['num_user'];
		}
		
	public function get_online_key(){
		$query = "SELECT key_user FROM online_users ORDER BY data_last_log ASC";
		$result = mysql_query($query) or die(mysql_error());
		$online = array();
		while($row = mysql_fetch_array($result)){
			$online[] = stripslashes($row['key_user']);
			}
		return $online;
		}
}

 

Analizziando il costruttore (e i commenti presenti) si potrà  notare come la logica seguita rispecchia esattamente quanto descritto inizialmente in termini teorici.

 

L'applicazione della classe sarà molto semplice:

<?php
$conn = mysql_connect('localhost', 'root', '') or die(mysql_error());    
$selezione_db = mysql_select_db('test', $conn) or die(mysql_error()); 

require_once('onlineusers.class.php');
$onlineIP = New OnlineUsers;
?>
<html>
<head>
<title>Utenti Online</title>
</head>
<body>
<?php
// number
$numero = $onlineIP->get_count_online();
echo '<h3>Number users online: '. $numero .'</h3>';

if($numero>=1){
	echo '<ul>';
	// ip online
	$log = $onlineIP->get_online_key();
	foreach($log as $log){
		echo '<li>' . $log . '</li>';
		}
	echo '</ul>';
	}
?>
</body>
</html>

 

Conoscendo l'IP dell'utente loggato volendo sarà possibile risalire alla sua localizzazione utilizzando alcuni servizi/script presenti sul web (ipinfodb).

 

IP dinamici e IP condivisi

Questa parte dell'articolo è dedicata ai più scrupolosi.

 

La classe ipotizza che l'IP possa identificare univocamente l'utente. Ciò non è esattamente corretto:

  • nell'ambito di reti LAN (più pc con un'unica connessione wireless) o nel caso di utenze di fastweb localizzate nelle vicinanze, vi saranno più utenti con lo stesso IP (ip condivisi);
  • il medesimo utente durante la navigazione può modificare il suo ip (ip dinamici).

 

Per ovviare a questi problemi (che nalla maggior parte dei siti a traffico medio-basso sono, a mio parere, trascurabili) occorrerà modificare il metodo get_key e far ricorso ai cookie.

La key che identificherà l'utente sarà generata tramite la funzione php uniqid() e salvarta all'interno di un cookie.

 

Sarà sufficiente modificare il metodo get_key() il quale diventerà:

protected function get_key(){
	$cookie_name = 'key_online_user';
	if(isset($_COOKIE[$cookie_name])){
		return $_COOKIE[$cookie_name];
		}
	else{
		$key = uniqid();
		$duration = time() + ( 60 * $this->minute_finish );
		setcookie ($cookie_name, $key, $duration, "/");
		return $key;
		}
	}

 

Integrazione in un sistema di login

Nel caso in cui si vuol verificare gli utenti loggati online (presupponendo, quindi, un sistema di login alla base) il campo key_user sarà valorizzato con l'ID dell'utente loggato

Facendo riferimento ad un precedente articolo in cui descrivevo un semplice sistema di login l'ID dell'utente loggato veniva salvato all'interno della variabile di sessione $_SESSION['auth'].

 

In questo caso andremo così a modificare il costruttore della nostra classe OnlineUsers in questo modo:

public function __construct(){
	$this->key = isset($_SESSION['auth']) ? $_SESSION['auth'] : FALSE;
	$this->clear_table();
	if($this->key!= FALSE){
		if(!$this->isset_key()){
			$this->insert_key();
			}
		else{
			$this->update_data_key();
			}
		}
	}

 

E', inoltre, opportuno modificare la tipologia del campo key_user della tabella online_users che dovrà essere di tipo INT.

 

Il metodo get_online_key() ci restituirà, in questo caso, l'array degli ID degli utenti loggati; sarà semplice prevedere all'interno della classe OnlineUsers un ulteriore metodo get_username_online() che ci darà un array contenente gli username:

public function get_username_online(){	
	$IDs = $this->get_online_key();
	$IDs = array_filter($IDs, "is_int");
	$query = "SELECT id, username FROM users WHERE id IN (" .implode(',', $IDs). ")";
	$result = mysql_query($query) or die(mysql_error());
	$users_online = array();
	while($row = mysql_fetch_array($result)){
		$users_online[$row['id']] = $row['username'];
		}
	return $users_online;
	}

 

La logica seguita è (in parte) analoga a quella descritta in questo articolo del blog di Maurizio Tarchini.

 

Conclusioni

La semplice classe descritta è, pertanto, molto flessibile. Addirittura si potrebbe sviluppare un ibrido tra utenti loggati e non.

 

Per qualsiasi dubbi, problemi, riflessioni e critiche i commenti sono sempre graditi e si risponderà a tutti.

Olimpio Romanella

Sono un appassionato di Web Developing con un particolare debole per php. Mi dedico principalmente dello sviluppo back-end ed in particolare programmazione lato server con php, sviluppo di database relazionali MySql e progettazione di CMS di piccole e medie dimensioni.

Mi avvalgo del framework javascript Jquery, utilizzando molti dei suoi plugin e nei dei miei progetti utilizzo spesso il framework MVC Codeigniter.

6 Commenti presenti

avatar Olimpio Romanella

Olimpio Romanella

15 September 2018 ore 21:25

@Lorenzo: ciao, non ho testato il tuo codice ma mi sembra che usi la variabile $connection senza che sia stata inizilizzata.

avatar Lorenzo

Lorenzo

14 September 2018 ore 16:14

in versione per mysqli non funziona, ti posto il codice modificato

Class OnlineUsers{
protected $key;
protected $minute_finish = 10;

public function __construct(){
$this->key = $this->get_key(); // otteniamo la key
$this->clear_table(); // eliminiamo gli utenti "scaduti"
if(!$this->isset_key()){ // non esiste la key
$this->insert_key(); // allora la inseriamo
}
else{
$this->update_data_key(); // altrimenti aggiorniamo il timestamp
}
}

protected function isset_key(){
$result = mysqli_query($connection, "SELECT * FROM online_users WHERE key_user='" .mysqli_real_escape_string($connection, $this->key). "'") or die(mysqli_error());
if(mysqli_num_rows($result)>=1){
return TRUE;
}
return FALSE;
}

protected function update_data_key(){
$result = mysqli_query($connection, "UPDATE online_users SET data_last_log=NOW() WHERE key_user='" . mysqli_real_escape_string($connection, $this->key) . "'") or die(mysqli_error());
return TRUE;
}

protected function insert_key(){
$result = mysqli_query($connection, "INSERT INTO online_users SET key_user='" . mysqli_real_escape_string($connection, $this->key) . "', data_last_log=NOW()") or die(mysqli_error());
return mysqli_insert_id();
}

protected function clear_table(){
$result = mysqli_query($connection, "DELETE FROM online_users WHERE data_last_log<=DATE_SUB( NOW() , INTERVAL ". intval($this->minute_finish) ." MINUTE )") or die(mysqli_error());
return TRUE;
}

protected function get_key(){
$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'undefined';
return $ip;
}

public function get_count_online(){
$result = mysqli_query($connection, "SELECT COUNT(*) AS num_user FROM online_users ORDER BY data_last_log ASC") or die(mysqli_error());
$fetch = mysqli_fetch_array($result);
return $fetch['num_user'];
}

public function get_online_key(){
$result = mysqli_query($connection, "SELECT key_user FROM online_users ORDER BY data_last_log ASC") or die(mysqli_error());
$online = array();
while($row = mysqli_fetch_array($result)){
$online[] = stripslashes($row['key_user']);
}
return $online;
}
}


Hai qualche soluzione ?

avatar Luca

Luca

08 February 2013 ore 16:52

ragazzi siete bravi molto , mi aiutate ad inserire questi script nel mio sito?

avatar Luca

Luca

08 February 2013 ore 16:50

come posso implementare il mio sito con questo script ... vorrei far tesoro delle vostre pagine ,ma non riesco a collegarle

avatar oly1982

oly1982

18 December 2011 ore 15:09

avatar matador

matador

17 December 2011 ore 22:29

Come posso rendere visibile l'array get_username_online()?
Funziona il count degli Users Online, ma vorrei poter indicare anche l'username...
Al posto della Sessione 'auth' ho inserito il COOKIE che setto al Login, e modificato la Quety per il mio DataBase, ma non riesco a rendere visibile la lista..
Come posso fare? Grazie :)