[web] PHP File reading/writing question

Started by
6 comments, last by markr 17 years, 9 months ago
let's say i want to make a counter of total visitor...and i don't have a database (let's say i can't use one, because it's in the spec). now i can use a file in PHP right? my problem is, won't there be a concurrency issue? like if both users access the file, whose current count is 32, then both of them would've updated the file to 33, when it should be 34 already (since there are 2 of them who viewed the site). does this happen in PHP? how to solve this? thanks!
Advertisement
Well you set a cookie so there won't be any trouble that way...the code checks if you have been on the site before...

[source language="php"]<?php $visitor_ip = $HTTP_COOKIE_VARS["user_ip"]; $counter = "counter.txt"; $counter_file_line = file($counter); if(!$visitor_ip) {   setcookie("user_ip", $REMOTE_ADDR, time()+360000);   $counter_file_line[0]++;   $cf = fopen($counter, "w+");   fputs($cf, "$counter_file_line[0]");   fclose($cf); } elseif($visitor_ip != $REMOTE_ADDR) {   $counter_file_line[0]++;   $cf = fopen($counter, "w+");   fputs($cf, "$counter_file_line[0]");   fclose($cf); } ?> 


This code checks if you have been on the page with the same ip address, if you have, it writes a notation and close the file again. Else it sets a cookie and writes to the file and close it.
alright got it! thanks! :)

I have another problem though, how to write new line in a file? I've tried the \n character, but it doesn't work?

here's my code sample:

fputs($fptr, "Hello\nWorld");


But I get "HelloWorld" as a result. Why?

thanks.
\n works, but not in notepad. Try opening the file in something like wordpad and you will notice the newlines, if you want to fix this problem use \r\n (windows linebreak)
-->My Site<--
oh you're right...hmm...if i use \r\n instead, will there be any issue in other OS (linux) when viewing that text file?

thanks!
As far as the concurrency issue is concerned, yes, this is a real issue. If you have a platform where file locking works properly (i.e. most platforms unless you're using a remote filesystem), you can do something like

$f = fopen("counter.txt", "r+"); // Notice mode - reading *AND* writing.flock($f, LOCK_EX); // Should block the thread until an exclusive lock is available// Now read the old counter$count = (int) stream_get_contents($f);$count ++;// Rewind and truncate the file (NOTE: we must NOT close the file, that would create a race condition)        fseek($f, 0);        ftruncate($f, 0);fwrite($f, $count); // write the new counterfclose($f); // automatically unlocks our lock.


Besides a bit of error checking (depends on your error handler; mine throw an exception on any warning or notice of any kind)- that should work. Untested.

Mark
i see...alright i'll try that markr. thanks!!
Obviously test it by:

- Running it from the CLI
- Stick a massive sleep() in between the read and write in the above
- Run several copies at once to ensure that the locking really does work

Don't just trust that it's right.

Mark

This topic is closed to new replies.

Advertisement