OVH Cloud OVH Cloud

compteur simple

7 réponses
Avatar
christov
afin de ne pas réinventer la roue en permanence.

Je recherche un script qui permet de compter le nombre de requêtes vers
certaines des pages du site, sans utiliser de cookies, ni de base de
données.

7 réponses

Avatar
bruno
Re Bonjour le compteur .....

<? // Compteur PHP de hits
$fichier="compteur.txt";
// Lecture du fichier s'il existe et incrémente
$cpt = 1;
if(file_exists($fichier)) {
$inF = fopen($fichier,"r");
$cpt = INTVAL(TRIM(fgets($inF, 4096))) + 1;
fclose($inF);
}
echo "$cpt visites";
// Sauvegarde du compteur
$inF = fopen($fichier,"w");
fputs($inF,$cpt."n");
fclose($inF);
?>


--
bien cordialement Bruno
°v° généalogie : www.bidouille.c.la
/(_) radio : www.rcf-lumieres.c.la
^^ église : www.erf-avignon.c.la
Avatar
VAUTHIER Christophe
soit plus precis dans ta demande. c une sorte de compteur de visite que tu
veux faire ? Si pas de base de données, tu stockes les nombres ou ? fichiers
?

++
"christov" a écrit dans le message de news:
4281c586$0$25041$
afin de ne pas réinventer la roue en permanence.

Je recherche un script qui permet de compter le nombre de requêtes vers
certaines des pages du site, sans utiliser de cookies, ni de base de
données.


Avatar
__marc.quinton__
bruno wrote:

<? // Compteur PHP de hits
$fichier="compteur.txt";
// Lecture du fichier s'il existe et incrémente
$cpt = 1;
if(file_exists($fichier)) {
$inF = fopen($fichier,"r");
$cpt = INTVAL(TRIM(fgets($inF, 4096))) + 1;
fclose($inF);
}
echo "$cpt visites";
// Sauvegarde du compteur
$inF = fopen($fichier,"w");
fputs($inF,$cpt."n");
fclose($inF);
?>


oui, c'est tout a fait cela, mais il manque la gestion
d'un verrou sur le fichier.

sur un petit site, ca ne fera rien, sur un plus gros site,
les risques de collisions sont considérablement majorés
proportionnelement au nombre de hits.

Avatar
Vincent Lascaux
a écrit dans le message de news:
d5vckn$91m$
bruno wrote:

<? // Compteur PHP de hits
$fichier="compteur.txt";
// Lecture du fichier s'il existe et incrémente
$cpt = 1;
if(file_exists($fichier)) {
$inF = fopen($fichier,"r");
$cpt = INTVAL(TRIM(fgets($inF, 4096))) + 1;
fclose($inF);
}
echo "$cpt visites";
// Sauvegarde du compteur
$inF = fopen($fichier,"w");
fputs($inF,$cpt."n");
fclose($inF);
?>


oui, c'est tout a fait cela, mais il manque la gestion
d'un verrou sur le fichier.

sur un petit site, ca ne fera rien, sur un plus gros site,
les risques de collisions sont considérablement majorés
proportionnelement au nombre de hits.


Il suffit pour éviter ce probleme de ne faire qu'un seule ouverture de
fichier. Quelque chose comme ca :

while(($f = fopen($fichier, "w+")) === false)
usleep(100000); // attend qu'une éventuelle autre écriture soit
terminée

$nombre = fread($f, 1024);
if(empty($nombre))
$nombre = 1;
else
$nombre++;
fseek($f, 0);
fwrite($f, $nombre);
fclose($f);

//A partir d'ici on peut utiliser $nombre pour l'afficher éventuellement sur
la page

--
Vincent


Avatar
__marc.quinton__
Vincent Lascaux wrote:

Il suffit pour éviter ce probleme de ne faire qu'un seule ouverture de
fichier. Quelque chose comme ca :

while(($f = fopen($fichier, "w+")) === false)
usleep(100000); // attend qu'une éventuelle autre écriture soit
terminée


je ne crois pas que ce soit une bonne idée ... si j'ai bien compris, tu
considere que l'on ne peut pas ouvrir 2 fois le meme fichier ?

j'ai trouvé cela dans les commentaires de fopen, en chercher lock et qui devrait convenir.

<?php
#going to update last users counter script since
#aborting a write because a file is locked is not correct.

$counter_file = '/tmp/counter.txt';
clearstatcache();
ignore_user_abort(true); ## prevent refresh from aborting file operations and hosing file
if (file_exists($counter_file)) {
$fh = fopen($counter_file, 'r+');
while(1) {
if (flock($fh, LOCK_EX)) {
#$buffer = chop(fgets($fh, 2));
$buffer = chop(fread($fh, filesize($counter_file)));
$buffer++;
rewind($fh);
fwrite($fh, $buffer);
fflush($fh);
ftruncate($fh, ftell($fh));
flock($fh, LOCK_UN);
break;
}
}
}
else {
$fh = fopen($counter_file, 'w+');
fwrite($fh, "1");
$buffer="1";
}
fclose($fh);

print "Count is $buffer";

?>


et voici un autre programme qui prouve que l'ouverture en ecriture n'est pas exclusive ;
de meme, il y a 2 classes File et Locked_File permettant l'acces a des fichiers avec
gestion interne des verrous. Ces 2 classes ne sont pas franchement testées, mais sont
correctes sur le plan de la syntaxe php.

#!/usr/bin/php
<?php

error_reporting(E_ALL);

class File{

var $fp;
function File($name, $mode){
$this->__construct($name, $mode);
}

function __construct($name, $mode){
$this->fp = fopen($name, $mode);
if($this->fp === false)
$this->error(sprintf('File(%s,%s)', $name, $mode));
}

function write($str){
fwrite($this->fp, $str);
}

function gets(){
return fgets($this->fp);
}

function close(){
return fclose($this->fp);
}
function error($string){
echo "error : $stringn";
exit(1);
}
}

class Locked_File extends File{
function Locked_File($name, $mode){
$this->__construct($name, $mode);
}

function __construct($name, $mode){
parent::__construct($name, $mode);
$this->lock();
}

function close(){
$this->unlock();
parent::close();
}
/*
To acquire a shared lock (reader), set operation to LOCK_SH (set to 1 prior to PHP 4.0.1).
To acquire an exclusive lock (writer), set operation to LOCK_EX (set to 2 prior to PHP 4.0.1).
*/

function lock($mode = LOCK_EX){
return(flock($this->fp, $mode));
}

function unlock(){
return (flock($this->fp, LOCK_UN));
}


}

$file = 'test.txt';
if(file_exists($file))
unlink($file);

# create file with some content
$f = new File($file, 'w+');
$f->write('hello');
$f->close();

# read file;
$f = new File($file, 'r');
$txt = $f->gets();
$f->close();

echo "# you may see 'hello' for file content : n";
echo "content = '$txt'n";

# try to open 2 times same file
$f1 = new File($file, 'w+');
$f2 = new File($file, 'w+');

$f1->write("I am f1n");
$f2->write("I am f2n");

echo "n# you may see 'I am f2' : n";
readfile($file);

$f1->close();
$f2->close();


$f = new Locked_File($file, 'w+');
$f->write('pid = ' . getmypid());
$f->close();

$pid = getmypid();
echo "n# you may see 'pid = ' $pid: n";
readfile($file);



?>

Avatar
Vincent Lascaux
Il suffit pour éviter ce probleme de ne faire qu'un seule ouverture de
fichier. Quelque chose comme ca :

while(($f = fopen($fichier, "w+")) === false)
usleep(100000); // attend qu'une éventuelle autre écriture soit
terminée


je ne crois pas que ce soit une bonne idée ... si j'ai bien compris, tu
considere que l'on ne peut pas ouvrir 2 fois le meme fichier ?


Effectivement, je pensais qu'on pouvait ouvrir un fichier en lecture
uniquement s'il n'était pas ouvert en écriture, et qu'on ne pouvait ouvrir
un fichier en écriture uniquement s'il n'était pas ouvert du tout.
En regardant la doc de flock sur php.net, je pense que tu as raison : c'est
faux... Je suis assez surpris de voir qu'un OS accepte qu'un fichier soit
ouvert plusieurs fois en écriture... Je ne pensais même pas que c'était de
la responsabilité de PHP de locker le ficiher lors de l'ouverture, je
pensais que l'OS s'en assurait lui même...

--
Vincent


Avatar
__marc.quinton__
pour le fun, une version avec une classe compteur. La classe File
a été complétée pour les besoins. La classe Locked_File fonctionne
(testée dans un environnement simple).


#!/usr/bin/php
<?php

error_reporting(E_ALL);

class File{

var $fp;
function File($name, $mode){
$this->__construct($name, $mode);
}

function __construct($name, $mode){
$this->fp = fopen($name, $mode);
if($this->fp === false)
$this->error(sprintf('File(%s,%s)', $name, $mode));
}

function write($str){
fwrite($this->fp, $str);
}

function gets(){
return fgets($this->fp);
}

function read($size = 1024){
return fread($this->fp, $size);
}

function rewind(){
return rewind($this->fp);
}

function seek($pos, $func = SEEK_SET){
fseek($this->fp, $pos, $func);
}

function close(){
return fclose($this->fp);
}
function error($string){
echo "error : $stringn";
exit(1);
}
}

class Locked_File extends File{
function Locked_File($name, $mode){
$this->__construct($name, $mode);
}

function __construct($name, $mode){
parent::__construct($name, $mode);
$this->lock();
}

function close(){
$this->unlock();
parent::close();
}
/*
To acquire a shared lock (reader), set operation to LOCK_SH (set to 1 prior to PHP 4.0.1).
To acquire an exclusive lock (writer), set operation to LOCK_EX (set to 2 prior to PHP 4.0.1).
*/

function lock($mode = LOCK_EX){
return(flock($this->fp, $mode));
}

function unlock(){
return (flock($this->fp, LOCK_UN));
}
}

class File_Counter extends Locked_File{
var $counter;

function File_Counter($name){
$this->__construct($name);
}

function __construct($name){

if(!file_exists($name)){
$this->counter = 0;
# create file ....
parent::__construct($name, 'a+');
} else {
parent::__construct($name, 'r+');
$this->counter = $this->_get();
}
}

function get(){
return $this->counter;
}

function set($val){
$this->counter = $val;
}

function increment(){
$this->counter++;
}

# get from file;
function _get(){
$line = $this->gets();
if($line === false){
trigger_error("error reading file"); exit(1);
}

$line = trim($line);
str_replace("n", '', $line);
return $line;
}

function close(){
$this->seek(0);
$this->write(intval($this->counter));
parent::close();
}
}

$file = 'counter.txt';

$c = new File_Counter($file);
$c->increment();
$val = $c->get();
$c->close();

echo "counter = $valn";


?>