|
|
Il y a actuellement 301 tutoriaux sur Aidoforum. Toute reproduction, partielle ou complète, est interdite.
Retour aux tutoriaux.
|
| PHP / MySQL -> Compteur de visites à l'ip sans MySql |
Réaliser un compteur sans bases de données dont le mode de stockage soit aisé n'est pas si difficile que ça. Toute fois si vous possédez une base de données, MySql par exemple, inutile de vous en priver ;-).
Le script, résumé à la fin de ce tutoriel, possède une petite dizaine d'étapes toutes simple que nous allons voir au fur et à mesure. Mais avant ça, regardons plutôt le concept du programme.
Les tableaux indexés, petit cours de rattrapage ;-)
Tout le compteur est basé sur une variable de type « array », un tableau qui n'est ni plus ni moins qu'un ensemble de données. Les variables de ce type ce présentes sous une forme particulière, en effet les variables simples de type string (chaîne de caractères) ou int (entier) float (à virgule flottante) double (décimaux) et booléen (vrais faux) associent une valeur unique à la variable ainsi
<?php
$variable = "ma chaîne de caractères";
echo $variable;
?>
|
affiche
alors que dans un tableau il existe une valeur associée à chaque clés.
Soit les clés sont numérotés dans l'ordre à partir de 0 et on dit alors que le tableau est indexé, soit les clés sont des chaînes de caractères (plus ou moins arbitraires) et on dit alors que le tableau est associatif (soit dit en passant, il peut très bien être les deux), ainsi
<?php
$tableau_indexe = array('valeur 1', 'valeur 2', 'valeur 3');
print_r($tableau_indexe);
$tableau_associatif = array(
'clée1' => 'valeur 1',
'clée2' => 'valeur 2',
'clée3' => 'valeur 3'
);
print_r($tableau_associatif);
?>
|
renvoi
Array
(
[0] => valeur 1
[1] => valeur 2
[2] => valeur 3
)
Array
(
[clée1] => valeur 1
[clée2] => valeur 2
[clée3] => valeur 3
)
|
On accède à une valeur grâce à sa clé :
<?php
echo $tableau_indexe[0];
echo "<br />\n"; // retour à la ligne
echo $tableau_indexe[2];
echo "<br />\n";
echo $tableau_associatif['clée2'];
?>
|
renvoi
valeur 1
valeur 3
valeur 2
|
Dans le cas de notre compteur
le tableau s'appelle « $donnees » et associe à la clé « visites » le nombre de visiteurs et à la clé « requêtes » le nombre de fois que le compteur à été exécuté, autrement dit, le nombres de pages affichés. Les autre clés étant les ip des visiteur et associant la date à laquelle elles ont été enregistrés. Par exemple :
Array
(
[requêtes] => 7
[visites] => 2
[56.47.2.387] => 20050714201032
[217.8.456.87] => 20050714235959
)
|
Comment stocker ce tableau ?
La fonction « serialize() » permet de transformer un objet en chaîne de caractère et « unserialize() » effectue l'opération inverse.
En effet, quitte à enregistrer les données dans un fichier plutôt que dans une base de donnée, autant le faire sous forme de chaînes de caractères se qui facilite la manipulation.
Où stocker ces données ?
Dans un ficher que le script crée. Par exemple « .htcompteur » qui est un fichier nommé « compteur » auquel on a ajouter « .ht » au début pour interdire son accès depuis Internet et le rendre invisible (en fichier caché) grâce au « . ». Ainsi notre mode de stockage est transparent et sécurisé !
Les étapes du script
Le script commence par un petit bloc tout simple :
$fichier = '.htcompteur';
if( !file_exists($fichier) ) {
$fp = fopen($fichier, "w");
fwrite($fp, serialize(array()));
fclose($fp);
}
|
En effet lors de la première exécution, le fichier n'existe pas encore et ces trois lignes permettent de crée le fichier contenant notre tableau... vide.
Cette instruction renseigne sur le nom et le chemin du fichier
$fichier = '.htcompteur';
|
il est donc possible de le changer en
$fichier = '.htCompteurDePagesDeLaMortKiTu';
|
ou de le placer dans le dossier « tests »
$fichier = 'tests/.htcompteur';
|
bref, vous en faites ce que vous voulez !
$fichier = 'includes/donneesducompteur.txt';
|
ensuite, la ligne
$fp = fopen($fichier, "w");
|
crée le fichier et l'ouvre avec des droit d'écriture, la ligne
fwrite($fp, serialize(array()));
|
enregistre dans le fichier un tableau vide sous forme de chaîne de caractères et
referme le fichier.
Notre système en mains, il ne nous reste plus qu'a réaliser le compteur en lui même qui va se dérouler suivant ces étapes :
- une petite série de définition de quelques variables nécessaires
- la récupération des données stockés,
- la suppression des données périmés,
- l'incrémentation (?) des compteurs,
- la définition de variables stockant les données utiles,
- le stockage des données actualisée,
- et l'affichage des valeurs du compteur.
Nos variables
Le nom des clés utilisées pour stocker la valeur des deux compteurs à savoir le nombre de visites et le nombre de pages affichés
$argument_visites = 'visites';
$argument_requêtes = 'requêtes';
|
la récupération de l'ip du visiteur
$ip = $_SERVER['REMOTE_ADDR'];
|
puis la date et l'heure lors que l'exécution de ce script
renvoi la date sous la forme d'un timestamp MySql...
Et pourquoi pas le timestamp Unix ?
Le timestamp Unix est le nombres de secondes s'étant écoulées depuis le 1er Janvier 1989.
Il a l'avantage certain de se présenter sous forme d'un entier et est utilisé pas de nombreux programmes pour manipuler les date. Seulement, en raison du nombre de chiffre limités, celui ci n'existera plus en 2039, ayant consommé toute la place, ce qui n'est pas le cas du timestamp Mysql qui n'est pas vraiment un timestamp mais une simple contraction d'une date complète telle que nous la connaissons. Ainsi le 14 Juillet 2005 à 23 heures, noté 2005-07-14 23:00:00 vas se retrouvé sous la forme 20050714230000.
Mon coté perfectionniste sûrement, me tend à utiliser cette deuxième solution, au moins je me dit que mon compteur ne sera pas périmé en 2039 (votre site peut être) ;-)
Bref
Le script récupère donc les données contenu dans notre fichier
$lignes = file($fichier);
$donnees = unserialize($lignes[0]);
|
« $lignes » est un tableau indexé contenant une ligne du fichier par clés, « unserialize($lignes[0]) » rend la forme d'un tableau à nos donnés contenu dans la ligne 1. Nous voici donc avec notre tableau « $donnees » prêt à l'emploi !
foreach( $donnees as $cle => $valeur )
{
if( substr($valeur, 0, 8) != substr($time, 0, 8) &&
$cle != $argument_visites &&
$cle != $argument_requêtes ) {
unset($donnees[$cle]);
}
}
|
Une boucle passe en revue toutes les clés du tableau tout en vérifiant que la clé est bien une ip, la supprime si la date « date » d'hier.
Décomposons.
&& $cle != $argument_visites && $cle != $argument_requêtes
|
Exclu les deux clés stockant les valeurs du compteurs.
Ne prend en compte que les 8 premiers caractère de la chaîne, ainsi seul la différence de date est testé et non l'heure.
Oui mais alors, pourquoi stocker l'heure ?!
Arf ben, c'est le « ça peut toujours servir » qui gagne ! Et oui, imaginons que vous vous sentez de faire un autre petit script qui, sur le modèle du début de celui ci récupère les donnée et les affiche, et ben paf!, vous avez de quoi surveillé les heures de passages (enfin d'arrivée) des visiteurs. Et en en remettant une couche, il est possible de stocker rapidement l'url par laquelle ce compteur à été exécuté (où le visiteur se trouve sur le site) ainsi que l'heure et l'ip correspondante, bref un vrai script d'espionnage des visiteurs, ou plutôt un script de statistiques.
Les compteurs sont ensuite incrémenté
« incrémenté » !?? moi parlé ~&*/ et toi rien comprendre ? Ok, ça veut surtout dire que l'on ajoute 1 à un nombre. Je vous épargne de la pré-incrémentation, post-incrémentation, pré-décrémentation, post-décrémentation (pour l'instant) mais bon, c'est tout juste une histoire de +1, -1 ;-).
$donnees[$argument_requêtes]++;
if( !$donnees[$ip] ) {
$donnees[$argument_visites]++;
$donnees[$ip] = $time;
}
|
À noté qu'on incrémente la valeur requête à chaque fois alors que celle des visiteur l'est si et seulement si (ma prof de math déteint sur moi !) le visiteur n'a pas encore été enregistrée.
Et donc si ce n'est pas le cas, on ajoute la date associée à l'ip et on incrémente les visites
$donnees[$argument_visites]++;
$donnees[$ip] = $time;
|
Ensuite...
Alors ça
$nb_visiteurs = $donnees[$argument_visites];
$nb_aujourdhui = count($donnees)-2;
$nb_requêtes = $donnees[$argument_requêtes];
|
c'est juste pour faire joli ici
echo $nb_visiteurs." visiteurs dont ";
echo $nb_aujourdhui." aujourd'hui, ";
echo $nb_requêtes." pages affichés ";
|
c'est beau hein ? Plus sérieusement, le nombre de visiteurs journaliers sont obtenu simplement en comptant le nombre d'ip enregistrés, c'est à dire ne nombre d'enregistrements que contient le tableau « $donnees » moins 2, à savoir « $donnees['visites'] » et « $donnees['requêtes'] ».
On enregistre nos données
$fp = fopen($fichier,"w");
fwrite($fp, serialize($donnees));
fclose($fp);
|
Ça ressemble quand même à du déjà vu...
On affiche fièrement le compteur
echo $nb_visiteurs." visiteurs dont ";
echo $nb_aujourdhui." aujourd'hui, ";
echo $nb_requêtes." pages affichées ";
|
Quoi que, ces instruction peuvent êtres déplacées à l'endroit idéal pour afficher les résultats (après le script bien sur)
Si ce script se retrouve dans un page appelée « compteur.php », il est tout à fait possible de l'include dans une autre page en php comme ceci :
include_once('compteur.php');
|
ou directement dans une page html grâce à du javascript :
<script language="javascript" src="compteur.php"></script>
|
Voili voilou, il ne manque plus qu'une chose
Le script en entier
<?php
/*
* Si le fichier où l'on stock,
* les données n'existe pas encore
* on le crée.
*/
$fichier = '.htcompteur';
if( !file_exists($fichier) ) {
$fp = fopen($fichier, "w");
fwrite($fp, serialize(array()));
fclose($fp);
}
/*
* Définition de variables
* nécessaire au compteur :
* - deux termes constants,
* - l'ip du visiteur,
* - la date et l'heure.
*/
$argument_visites = 'visites';
$argument_requêtes = 'requêtes';
$ip = $_SERVER['REMOTE_ADDR'];
$time = date('YmdGis');
/*
* Récupération des données du
* compteur précédemment stockées.
*/
$lignes = file($fichier);
$donnees = unserialize($lignes[0]);
/*
* Pour chaque clés du tableau de données
* qui ne soit pas attribuée aux visite et aux requêtes
* si la valeur correspond à une date antérieur
* au même jour, on supprime l'ip du visiteur.
*/
foreach( $donnees as $cle => $valeur )
{
if( substr($valeur, 0, 8) != substr($time, 0, 8) &&
$cle != $argument_visites &&
$cle != $argument_requêtes ) {
unset($donnees[$cle]);
}
}
/*
* On incrémente ( ajoute +1 ) la valeur
* du nombre de requêtes.
* Si l'ip n'est pas encore enregistrée,
* on incrémente la valeur du nombre de visites
* et on ajoute l'ip dans le tableau accompagné
* de la date et de l'heure de l'exécution.
*/
$donnees[$argument_requêtes]++;
if( !$donnees[$ip] ) {
$donnees[$argument_visites]++;
$donnees[$ip] = $time;
}
/*
* On effectue un petit report de variable
* pour une utilisation ultérieur plus aisée.
*/
$nb_visiteurs = $donnees[$argument_visites];
$nb_aujourdhui = count($donnees)-2;
$nb_requêtes = $donnees[$argument_requêtes];
/*
* On stock le tableau dans le fichier de données
* en écrasant sa valeur précédente.
*/
$fp = fopen($fichier,"w");
fwrite($fp, serialize($donnees));
fclose($fp);
/*
* On affiche les résultats du compteur.
*/
echo $nb_visiteurs." visiteurs dont ";
echo $nb_aujourdhui." aujourd'hui, ";
echo $nb_requêtes." pages affichées ";
?>
|
Enjoy !
Arcus
|
| Par Arcus, le 05 Mai 2005 à 20h08 |
| Commentaire de Pouzy le 05 Mai 2005 à 20h52 | Wahou, ça c'est de l'énorme tuto comme on les aime ! :love:
|
| Commentaire de Ðarude le 05 Mai 2005 à 23h28 | franchement .... super joli et compréhensible
10/10 =D ( ou qu'il est le scipt pour noter les tutos ? )
|
| Commentaire de Arcus le 06 Mai 2005 à 10h50 | lol ... dans les commentaires ! ( style g le temps d'ajouter une notation aux tutoriaux... pouzy devra attendre encore un peu ;-) )
pour les suggestions, les points flou ( les demandes de tutos, pourquoi pas) c'est dans le forum Tutoriaux que ça se passe !
|
| Commentaire de swinggho le 06 Mai 2005 à 23h01 | bien joué arcus....
|
| Commentaire de ben.popeye le 05 Aout 2005 à 10h51 | Ouah, je vais changer le mien qui tourne sur mySQL pour celui-ci, c'est plus rapide que des requêtes!
Merci Arcus, ça nous évite de s'embêter...
|
| Commentaire de Jubei le 08 Septembre 2005 à 14h00 | excellent tuto, merci
|
| Commentaire de Alainb le 05 Octobre 2005 à 01h58 | Très bien, ça m'a fait comprendre un peu mieux l'écriture et la lecture dans un fichier.
Cela dit, il existe une petite erreur logique : tu effaces l'ip des visiteurs de la veille avant de vérifier si l'ip du visiteur connecté existe, pour incrémenter le nombre total de visiteurs. Ce qui fait qu'un visiteur connecté à 23h55 (par exemple) et qui reste connecté jusqu'après 00h00 va compter pour deux dans le nombre total de visites (j'ai fait l'essai). Pour corriger ce petit bug j'ai donc rajouté à la suite de ton script le code suivant:
$fichier_total = '.htcompteur_total';
if( !file_exists($fichier_total) ) {
$fp = fopen($fichier_total, "w");
fwrite($fp, serialize(array()));
fclose($fp);
}
$duree_sess_max = 43200;//durée de stockage de l'ip avant effacement (exprimé en seconde et modifiable, ici 12h).
$argument_visites_total='visites_total';
$ip = $_SERVER['REMOTE_ADDR'];
$date = strtotime("now");
$lignes_total = file($fichier_total);
$donnees_total = unserialize($lignes_total[0]);
foreach( $donnees_total as $cle => $valeur )
{
if ($cle != $argument_visites_total && ($date - $valeur > $duree_sess_max ))
{
unset($donnees_total[$cle]);
}
}
if( !isset($donnees_total[$ip]) ) {
$donnees_total[$argument_visites_total]++;
$donnees_total[$ip] = $date;
}
$nb_visiteurs = $donnees_total[$argument_visites_total];
$fp = fopen($fichier_total,"w");
fwrite($fp, serialize($donnees_total));
fclose($fp);
?>
Je rappelle qu'il s'agit d'un complément à mettre à la suite du code original (avant l'affichage des résultats) sinon vous n'obtiendrez qu'un compteur de visites totales (des bouts de code sont redondants avec l'original pour permettre une utilisation autonome de ce script comme simple compteur de visites totales).
Petite contrariété, il y aura peut-être des pb de fonctionnement en 2039...Je ne précise pas pourquoi, pas plus que je ne rentre dans l'explication du code puisque c'est la mise en application du tuto très bien documenté d'Arcus (encore une fois, merci Arcus) avec un timestamp Unix.
Si vous avez la soluce pour faire aussi simple et éternel...merci de nous le faire savoir.
Ah oui, une dernière précision: pour que ces scripts fonctionnent chez un hébergeur professionnel vous aurez peut-être besoin (ça dépend des serveurs) de donner l'autorisation de lecture et d'écriture sur les fichiers ".htcompteur" ou/et ".htcompteur_total" au niveau du serveur. Par exemple dans FileZilla (logiciel ftp gratuit, voir google) clic droit sur le fichier distant en question puis "attributs de fichiers" puis indiquer 777 ou cocher toutes les cases (pas sûr du tout que dreamweaver ait cette fonctionnalité dans son module de transfert ftp).
|
| Commentaire de rafarel le 14 Avril 2006 à 20h28 | Salut Arcus.
J'ai fait mon compteur de visite en m'inspirant de ton code.
Le problème c'est que le compteur se reinitialise de temps en temps et c'est tres enuyeux! (au alentour des 2000 a 3000 visites)!
Sais tu d'ou cela pourrais venir?
Merci
|
| Commentaire de Arcus le 17 Avril 2006 à 21h08 | Merci Alainb et rafarel pour vos apports
Je ne ne vérifi malheureusement pas assez les commentaires des tutos (pensez à poser vos questions sur le forum ;-) )
- pour Alainb merci c'est très juste pour l'histoire du visiteur qui se pointe juste avant minuit, mais rien à été ajouté pour souci de simplicité (hélas oui je t'entend lol)
Dans le même genre il y a les visiteurs derriere un routeur, à la maison de plus en plus ou en entreprise qui ne sont pas différenciés car possédant la même adresse ip... mais bon, les défauts comme les avantages sont dans le titre ! Pour moi c'est parfait pour une mini page web faite à "l'arache" mais surement pas pour un site en entier que l'on édite régulièrement.
Après le mieux c'est sur c'est toujours d'utiliser une table mysql ou deux pour contabiliser les statistiques de visites, durées, navigateurs différents utilisés... différencier les visiteurs tant sur leur ip qu'a l'aide de sessions etc...
-pour répondre à rafarel:
je n'est pas observé de bug mais cela ne m'étonne gère dans le sens ou je n'ai pas vraiment pris le temps dans la mesure ou je n'utilise pas ce compteur...
Si ton pb est encore d'actualité, poste un sujet dans aide au site web, je ne serai pas le seul à t'aider ;-)
|
| /!\ Vous devez être inscrit pour pouvoir commenter ce tutoriel, ou demander du support. /!\ |
|
|
|
|
|