PHP hit counter
Here, for what it’s worth, is my attempt at a very simple hit counter for a PHP-based web site. It’s similar to the day when I first brought a horn home from school and played it, much to the delight of my family – “Yes, very nice dear. Why don’t you take it outside?” In other words, it’s a bit crap but I’m proud of it nonetheless.
Scripts such as these are a doddle in ASP or any other language with application handling features, but PHP requires a little cheating ingenuity. This script, in a nutshell, checks the current user’s session ID against one stored on a flat file. If they don’t match, the count is incremented. This means that the counter deals in visits across the whole site rather than hits on one page, or total hits on all pages.
If you want to use it yourself, you’ll need to download the following two files: hitcounter.php and hits.txt. Create a directory called “application” in your site’s root folder and upload the files there.
Next step is to make sure all your pages are in PHP format (I won’t patronise you further by reminding you that your host needs to have PHP installed). At the very top of each page paste the following line of code:
<?php include_once("application/hitcounter.php"); ?>
Finally, this line of code goes in where you want the hit counter to appear:
<?php echo $count; ?>
That’s it! You’re all set. Try opening your site in different browsers simultaneously. You should see the count going up each time you open a new one.
How it works
<?php
session_start();
$newsid=session_id();
$data_path="application/hits.txt";
session_start() does exactly what it says on the tin and starts a new user session. Some servers are configured to do this automatically, but better safe than sorry. session_id() gets the bit of info that makes the whole thing tick, the unique identifier assigned to each session by the server. You can change the $data_path variable if you want to upload the files somewhere else.
$data=file_get_contents($data_path);
list($oldsid,$count)=explode("|",$data);
The text file is just one line containing two values (the previous session id and the current hit count) separated by a pipe(“|”) character.
if (strcmp($newsid,$oldsid)!=0) {
$count++;
$fh=fopen($data_path,"w");
fwrite($fh,$newsid."|".$count);
fclose($fh);
}
Here the values of the current ($newsid) and previous($oldsid) SIDs are compared. If they are different, then obviously we have another hit, so the count is incremented, and the file rewritten with the new SID and count value.
$counter="<div id="hitcounter">You are visitor number ".$count." to this site.</div>";
?>
Last but not least, the $counter variable is set up with the HTML markup to be displayed on the page.
Limitations
There are two problems with the script as it stands. I’m not sure how it’ll stand up to two or mor users trying to write to hits.txt simultaneously. ASP has an Application.Lock method that prevents this from happening, but I’m not sure if there’s a way to replicate this in PHP.
Secondly, and a more likely problem, is what happens when two users are even in the same vicinity. When user A moves from one page to another, the count will stay the same – assuming there are no other page requests during his session. If User B appears and increments the count himself, User A’s next page request will bump it up again, since the stored SID will have been changed. User B’s next request will move it up again, and so on, and so on. More than two users will of course compound this effect. If anyone has a way round this, I’d like to hear it, but bear in mind I’m aiming at a straightforward solution that will work on an out-of-the-box PHP installation, without having to mess around with extra modules.

January 23rd, 2006 at 6:32 pm
[...] I should really learn to read things properly. Two pages on in my PHP book was the section on session variables. One of which is the basis for this new, improved, go-faster version of my hit counter. Rather than rely on a number in a flat file, this method actually works by detecting the presence of a session on the client side, which makes a whole lot more sense. Here’s the code: [...]