Reputation: 781
I wrote this counter which keeps track of yes/no for a website and it works decently well, the problem is somehow the files get messed up while writing. For example: it'll go from 126 to 27. The script gets called from an iOS app I wrote so most likely there are multiple connections modifying the file at the same time and I think this is what is causing the problem. I am not really a PHP guy so I was hoping for some insight on what could make the code a little better and handle multiple simultaneous connects.
<?php
$yes_file = 'yes.txt';
$no_file = 'no.txt';
$yes_count = file_get_contents($yes_file);
$no_count = file_get_contents($no_file);
if ($_GET['result'])
{
if( strcmp($_GET['result'], "YES") ) {
$no_count+=1;
file_put_contents($no_file, $no_count);
}
else {
$yes_count+=1;
file_put_contents($yes_file, $yes_count);
}
}
$total = $yes_count + $no_count;
echo "{\"yescount\":" . $yes_count.",";
echo "\"nocount\":" . $no_count.",";
echo "\"total\":" . $total."}";
?>
Thanks!
Upvotes: 0
Views: 596
Reputation: 11999
First of all, I'd propose to use a database system to track counters.
Regarding your problem, it would be helpful to flock() the file during the read-update-write cycle. This could prevent race conditions.
Upvotes: 1
Reputation: 14131
This should be more efficient.
FYI, a database puts a write lock on the row/table whilst incrementing, which is the same as what I've done below, so a database is not the solution - the solution is a write lock (via a database or via PHP). You could use flock
, but I find that messy so I've done it just with a temporary file.
The only issue with my code here is that if the server crashes in the middle of this script then the write lock will stay in place (MySQL has this issue too sometimes). I usually get around this by writing the time()
in the file and checking that it is not older than an an hour or something. But in your case it's probably unnecessary.
<?php
// Your variables
$yes_file = 'yes.txt';
$no_file = 'no.txt';
if (isset($_GET['result']))
{
// Write lock
while(file_exists('temporaryfile')) usleep(100000);
file_put_contents('temporaryfile','1');
$yes_count = (int)file_get_contents($yes_file);
$no_count = (int)file_get_contents($no_file);
// Increment
if ($_GET['result']=='YES')
{
$yes_count++;
file_put_contents($yes_file, $yes_count);
}
else
{
$no_count++;
file_put_contents($no_file, $no_count);
}
// Unlock
unlink('temporaryfile');
}
else // No need for any lock so just get the vars
{
$yes_count = (int)file_get_contents($yes_file);
$no_count = (int)file_get_contents($no_file);
}
$total = $yes_count + $no_count;
echo "{\"yescount\":$yes_count,\n\"nocount\":$no_count,\n\"total\":$total}";
Upvotes: 1