Je vais présenter sur cette page un système de compteur de visites léger et relativement fiable. Ce système est programmé en PHP, en utilisant le mécanisme de cache et de requêtes conditionnelles de HTTP.
Cet exemple génère une image PNG
Nombre approximatif de visiteurs de cette page :
La procédure d'installation consiste à télécharger le script et une librairie, à les mettre dans un même répertoire,
sur un serveur Web supportant PHP, et à renommer leur extension en .php
Il ne reste plus qu'à s'assurer que PHP a les droits en lecture et écriture dans le répertoire où ces deux fichiers ont été placés.
En particulier, le script va sauver le nombre de visites dans le fichier meter.txt
,
et créer à chaque exécution un fichier temporaire mutex2.txt
qui est supprimé dès la fin du script, quelques millisecondes plus tard.
Pour tester que cela fonctionne, accédez via votre navigateur Web au fichier meter.png.php
Si vous testez en local, l'adresse sera de la forme http://localhost/compteur/meter.png.php
Si cela ne fonctionne pas, mettez temporairement les deux lignes error_reporting(E_ERROR);
et header('Content-type: image/png');
en commentaires afin de voir les éventuels messages d'erreurs.
En faisant cela, il est normal de voir une séquence de caractères étranges commençant par ‰PNG
ou similaire.
Lire ma documentation sur la configuration PHP sous Apache pour plus d'explications.
Une fois que le compteur fonctionne seul, il est temps de l'inclure dans une page Web. Cela se fait simplement en ajoutant une image, dont l'adresse est celle du script du compteur.
<html> ... <img src="meter.png.php" height="18" alt="[Compteur]" title="Nombre de visites" /> ... </html>
La largeur de l'image est automatique, et augmentera en fonction des visites.
Voici le code source du script du compteur.
meter.png.php <?php $session=1800; //En secondes $fmeter='meter.txt'; error_reporting(E_ERROR); header('Content-type: image/png'); require_once('http-conditional.php'); //Prenez cette librairie sur https://alexandre.alapetite.fr/doc-alex/php-http-304/ $begin=time(); $lastModif=max($begin-$session,filemtime($fmeter)); if (httpConditional($lastModif,$session,0,true,true)) exit(); //Cache 30 minutes, privé, compression ignore_user_abort(true); //<obtenir_mutex> $mutexFile1='mutex1.txt'; //Fichier à utiliser pour la méthode mutex#1 $mutexFile2='mutex2.txt'; //Fichier à utiliser pour la méthode mutex#2 $mutexOK=false; $mutexMethod=0; if (file_exists($mutexFile1)) {//Méthode mutex#1 (meilleure, mais ne marche pas sur beaucoup de systèmes) $mutexMethod=1; $fp=fopen($mutexFile1,'w+'); $mutexOK=flock($fp,LOCK_EX); } else {//Méthode mutex#2 (suppose fopen() atomique) $mutexMethod=2; if (file_exists($mutexFile2)&&($begin-filemtime($mutexFile2)>30)) {//Dans le cas où une vieille exécution n'a pas pu supprimer le fichier mutex. //Supporte les processus concurrents @chmod($mutexFile2,0666); unlink($mutexFile2); } $attempt=1; while (($attempt<50)&&(@fopen($mutexFile2,'x')===false)) { $begin2=time(); usleep($attempt*5000); //$attempt*10 millisecondes $usleep2=1000000; while (($usleep2>0)&&(time()-$begin2>$attempt*5000)) $usleep2--; //si usleep() ne marche pas $attempt++; } $mutexOK=($attempt<50); } //</obtenir_mutex> if ($mutexOK) { if($myMeter=fopen($fmeter,'r')) {//Lit le compteur courant $meter=trim(fgets($myMeter,22)); $lastIP=trim(fgets($myMeter,36)); fclose($myMeter); if (!is_numeric($meter)) $meter=0; } else { $meter=0; $lastIP=md5('127.0.0.0'); } $IP=md5($_SERVER['REMOTE_ADDR']); if (((time()-$clientCacheDate)>$session)&& !(($clientCacheDate<632003440)&&($IP==$lastIP))) //Légère protection contre les raffraîchissements abusifs {//Si la session a expiré, incrémente le compteur $meter++; if($myMeter=fopen($fmeter,'w')) { fputs($myMeter,$meter."\n"); fputs($myMeter,$IP."\n"); fclose($myMeter); } clearstatcache(); //Met à jour les entêtes HTTP avec les nouveaux "Last-Modified" et "ETag" httpConditionalRefresh(filemtime($fmeter)); } } else $meter='?'; //<rendre_mutex> switch ($mutexMethod) { case 1: flock($fp,LOCK_UN); fclose($fp); break; case 2: @chmod($mutexFile2,0666); unlink($mutexFile2); break; } //</rendre_mutex> $font=5; $im=imagecreate(5+2*$font*strlen($meter),18); $bg=imagecolorallocate($im,255,255,255); imagecolortransparent($im,$bg); $tc=imagecolorallocate($im,0,0,0); imagestring($im,$font,4,2,$meter,$tc); imagepng($im); imagedestroy($im); ?>
Ce contenu est protégé par une licence
Creative Commons Paternité - Partage des Conditions Initiales à l'Identique 2.0 France "BY-SA (FR)"