Comment faire pour afficher le nombre de connectés

Voici donc une petite astuce permettant de comptabiliser le nombre de visiteurs qui sont actuellement connectés sur votre site WEB.

On aurait très bien pu placer ce petit script dans la rubrique astuce de ce même site, mais la logique de ce script n'étant pas si évidente au premier abord que nous avons décidé de le placer dans cette rubrique comment faire.

En effet, il n'existe pas en PHP de solutions fiables à 100 % permettant de connaître le nombre exact de personnes connectés à un site et ce, à un temps T donné.

A première vue, on pourrait penser qu'avec des sessions cela serait possible.
En effet, dès que le visiteur se connecte, on l'enregistre dans une table de base de données, et dés qu'il quitte le site (en cliquant sur un bouton "déconnexion" par exemple), et bien il suffirait de l'enlever de cette table.
Ainsi, on aurait toujours dans cette table le nombre exact de clients qui sont connectes au site.
Oui, mais, parce qu'il y a un mais.
En effet, si le client ne quitte pas le site en cliquant sur le bouton de déconnexion, mais qu'il ferme simplement son navigateur : Comment savoir si il est réellement parti ou si il s'est simplement endormi sur la page d'accueil du site ?

Tout cela pour dire que seul le serveur hébergeant le site WEB en question peut révéler ce nombre de connexion : en effet, lorsqu'un client ouvre une connexion sur un serveur WEB via le protocole TCP, le client émet en fait une demande de connexion au serveur (via un message envoyé au serveur après avoir validé l'URL du site dans le navigateur), et celui-ci confirme ou refuse cette connexion en informant le client via un acquittement (un message simple du genre : "ok, j'accepte la connexion" ou "non, toi tu ne te connectes pas").
Le serveur connaît donc dans ses logs les personnes qui sont actuellement connectés sur le site puisque c'est lui-même qui "délivre" les connexions au site.

Enfin bon, on ne va pas vous faire un cours sur TCP, cela serait plutôt hors sujet, mais bref, tout cela pour dire que seul le serveur à "la connaissance" des clients qui sont connectés chez lui.

Comment faire donc pour que PHP, qui renvoie une page au format HTML à ses clients, puisse nous communiquer le nombre de clients connectés sur notre site (sachant que le "PHP n'est pas le serveur" et qu'il ne sait interpréter que du code PHP) ?

Et bien nous allons feinter.

En effet, nous n'allons pas chercher à savoir le nombre exact de clients connectés sur notre site à un instant T donné, mais nous allons plutôt calculer le nombre de clients qui ont chargé une page du site il y a moins de x minutes.

Pour rendre le tout réaliste, nous allons fixé ce temps x à 3 minutes.

En effet, on considère que si un client, au bout de 3 minutes, n'a pas chargé une seule du site, cela veut dire qu'il ne navigue plus sur le site (bien sur, ce temps est arbitraire : si vous estimez qu'il faut 5 minutes en moyenne pour lire une page de votre site, rien ne vous empêche de choisir un temps x de 5 minutes au lieu de 3).

Imaginons maintenant que notre site est visité par 2 visiteurs : A et B.

A se connecte sur le site et charge la page d'accueil du site.
On note alors l'adresse IP de A ainsi que son horaire de connexion dans une table SQL.
A lit la page sur laquelle il vient d'arriver.
B se connecte sur le site 2 minutes après A.
On note alors l'adresse IP de B ainsi que son horaire de connexion dans la même table SQL. Dans ce même temps, on regarde la table : on voit que A s'est connecté sur le site il y a 2 minutes. Or comme 2 < 3, cela veut dire que A est encore considéré comme connecté au site.
A ce moment là, on a donc deux clients en ligne.

A se déconnecte alors du site, mais il faut attendre qu'un client charge une page du site pour le savoir.
2 minutes après que B se soit connecté sur le site, B charge une seconde page du site.

On regarde alors la table SQL : nous avons deux tuples :
- un correspondant à A (avec l'heure à laquelle il a chargé pour la dernière fois une page WEB de notre site, heure qui date de plus de 3 mn) ainsi que son adresse IP.
- l'autre correspondant à notre client B (avec l'heure de la dernière page chargée, qui date donc de moins de 3 mn) ainsi que son adresse IP.

Comme nous considérons que A n'est plus connecté sur notre site WEB, nous allons effacer le tuple de notre table SQL le concernant, et en plus, nous allons mettre à jour notre table SQL pour le client B : en effet, B vient juste de charger une page WEB du site, et par conséquent, nous allons modifier son tuple en modifiant la date correspondant à la dernière page chargée pour le client par la date actuelle (puisque B vient juste de charger une page WEB).

Après avoir vu légèrement comment le script fonctionnait, nous allons voir maintenant comment le mettre en place.

Pour ce faire, nous allons avoir besoin d'une table SQL, que l'on nommera nb_online, et qui comprendra deux attributs :
- ip qui sera de type VARCHAR(15) et qui contiendra les adresses IP des clients du site
- time qui sera de type bigint(16), soit un entier à 16 chiffres contenant les dates des derniers chargement de pages de nos différents clients



Note :

En effet, pour une fois, nous n'allons pas utiliser un type date dans notre table pour représenter une date mais bel et bien un type entier, soit un chiffre.

Et pourquoi me direz-vous ?
Et bien, comme nous venons de le voir, à chaque fois qu'une page est chargée, nous allons regarder notre table SQL, et nous allons supprimer certains tuples de cette table.

Lesquels ?
Et bien, nous allons supprimer tous les tuples dont l'attribut time aura au moins 3 minutes de moins que la date à laquelle nous allons exécuter le script.

Or, faire des différences de minutes sur des dates, ce n'est pas une chose aisée.
Heureusement pour nous, en PHP, en passant l'argument U à la fonction date, nous obtenons en réalité le nombre de secondes écoulées depuis le 1er janvier 1970 : il nous suffira alors de faire une simple soustraction pour savoir si les dates contenues dans la table ont au minimum 3 minutes de moins que la date actuelle (toujours exprimée en secondes).

Par exemple :
- supposons qu'il y aient 1 049 924 865 secondes écoulées depuis le 1er janvier 1970 jusqu'au 10.04.2003 à 14 H 53 mn 17 s.
- un client se connecte sur le site 4 minutes plus tard : son temps sera donc de : 1 049 924 865 + (4 x 60) = 1 049 925 105 (secondes écoulées depuis le 1er janvier 1970).
- en faisant alors une simple soustraction entre ces dates, nous obtenons naturellement une différence de 4 x 60 = 240 secondes = 4 minutes.
- or, cette différence étant supérieur à 3 minutes (= 180 secondes), nous allons alors supprimer ce tuple de notre table.

Voici donc la structure de la table SQL que nous allons utiliser :

table_nb_online.sql
CREATE TABLE nb_online (
ip VARCHAR(15) NOT NULL,
time bigint (16) NOT NULL default '0'
) TYPE=MyISAM;


Voyons maintenant le code PHP de ce script.
Naturellement, il faudra le placer dans toutes vos pages PHP, et de préférence en "haut" de votre page.
Attention tout de même à placer avant ce script la connexion vers votre base de données.

Mon conseil : placer ce script dans un fichier appelé nombre_online.php, et par la suite, vous appellerez ce script en faisant un :

index.php
<?php
include 'nombre_online.php';
?>


Voici alors le code du script :

nombre_online.php
<?php
// on définit le nombre de secondes définissant l'intervalle de temps au cours duquel on considère qu'un client est toujours en ligne (ici 3 minutes = 180 secondes)
$tps_max_connex = 180;

// on récupère le nombre de secondes écoulées depuis le 1er janvier 1970
$temps_actuel = date("U");

// on prépare une requête SQL permettant de rechercher cette adresse IP dans notre table, afin de voir si le client qui charge la page n'est pas déjà comptabiliser (en clair : si on trouve l'adresse IP, cela veut dire que le client ne charge pas pour la première fois une page du site, et que donc, nous n'aurons juste à modifier le champs time du tuple le concernant ; si l'on ne trouve pas cette adresse IP dans la table, cela veut dire que soit le client n'a jamais chargé une page du site, soit il l'a fait, mais il y a plus de 3 minutes, ce qui implique qu'il a été supprimé de la table : et dans ces deux cas, il faudra l'insérer dans la table pour le comptabiliser comme étant un nouveau connecté).
$sql = 'SELECT count(*) FROM nb_online WHERE ip= "'.$_SERVER['REMOTE_ADDR'].'"';

// on lance la requête SQL (mysql_query) et on affiche un message d'erreur si la requête ne se passait pas bien (or die)
$req = mysql_query($sql) or die('Erreur SQL !<br />'.$sql.'<br />'.mysql_error());

// on comptabilise le nombre de résultats obtenus : soit 1, soit aucun (attention, aucun est différent de 0)
$data = mysql_fetch_array($req);

// on libère l'espace mémoire alloué pour cette requête SQL
mysql_free_result($req);

if ($data[0]) {
// si on a trouvé un résultat, on modifie le temps du tuple du client en conséquence : en effet, le client vient juste de charger une page WEB, on modifie alors le temps de son tuple par la date actuelle (en fait le nombre de secondes separant le 1er janvier 1970 de la date actuelle).
$sql = 'UPDATE nb_online SET time = "'.$temps_actuel.'" WHERE ip = "'.$_SERVER['REMOTE_ADDR'].'"';

// on lance la requête SQL (mysql_query) et on affiche un message d'erreur si la requête ne se passait pas bien (or die)
$req = mysql_query($sql) or die ('Erreur SQL !<br />'.$sql.'<br />'.mysql_error());
}
else {
// on entre dans ce cas si le client n'a jamais chargé de page (il est inconnu dans la table SQL car son IP y est absente). Dans ce cas, on insère alors dans la table SQL un nouveau tuple comprenant l'adresse IP de ce client ainsi que la date actuelle (le nombre de secondes entre le 1er janvier 1970 et la date actuelle).
$sql = 'INSERT INTO nb_online VALUES("'.$_SERVER['REMOTE_ADDR']. '", "'.$temps_actuel.'")';

// on lance la requête SQL (mysql_query) et on affiche un message d'erreur si la requête ne se passait pas bien (or die)
$req = mysql_query($sql) or die ('Erreur SQL !<br />'.$sql.'<br />'.mysql_error());
}

// on calcule le temps imparti pour comptabiliser les connectés au site (en fait, cela correspond à notre soustraction de tout à l'heure : on calcule la date limite pour que l'on considère que les clients soient encore connectés).
$heure_max = $temps_actuel - $tps_max_connex;

// on prépare une requête SQL permettant de supprimer les clients que l'on considère comme n'étant plus connectés (c'est à dire ayant expiré leur temps de 3 minutes défini comme étant le temps moyen de lecture d'une page WEB).
$sql2 = 'DELETE FROM nb_online where time < "'.$heure_max.'"';

// on lance la requête SQL (mysql_query) et on affiche un message d'erreur si la requête ne se passait pas bien (or die)
$req2 = mysql_query($sql2) or die ('Erreur SQL !<br />'.$sql2.'<br />'.mysql_error());
?>


Et voilà :)
Le script est à présent en partie terminé.

En effet, il n'est pas fini car pour l'instant le script ne s'occupe que de la gestion de la table SQL et il ne propose aucun affichage du nombre de connectés sur le site.
Pour ce faire, au moment où nous désirions afficher sur notre page le nombre de client connecté sur le site, il faudra inséré par exemple le code suivant :

index.php
<?php
$base = mysql_connect ('serveur', 'login', 'password');
mysql_select_db ('nom_base', $base);

include ('nombre_online.php');
?>
<html>
<head>
<title>Howto online</title>
</head>

<body>

<?php
// on prépare une requête SQL permettant de compter le nombre de tuples (soit le nombre de clients connectés au site) contenu dans la table
$sql = 'SELECT count(*) FROM nb_online';

// on lance la requête SQL (mysql_query) et on affiche un message d'erreur si la requête ne se passait pas bien (or die)
$req = mysql_query($sql) or die('Erreur SQL !<br />'.$sql.'<br />'.mysql_error());

// on récupère le nombre de tuples obtenus
$data = mysql_fetch_array($req);

// on libère l'espace mémoire alloué pour cette requête SQL
mysql_free_result($req);

echo 'Il y a actuellement ' , $data[0] , ' personne(s) surfant sur ce site.';
?>

</body>
</html>


Enfin :)
LoadingChargement en cours