PHP: Locking files

tenx23

New Member
Messages
25
Reaction score
0
Points
0
Ok, so I have a file... for the sake of simplicity we will call it "file.txt"...

I also have a PHP script that edits that text file...

I have one problem:

If two users use the PHP script at the same time, the file.txt file will mess up and be unreadable by my parsing script! I also want a wait to wait, say 100 milliseconds.

I need:
-a way to lock the file
-a way to check if the file is locked
-a way to unlock the file

If you are saying use a file and check for it's existance, I can't do that.


I'm looking for a solution a bit like:

Code:
<?php
$canleave = false; //loop escape variable
while (! $canleave) {
$r = lock_file('file.txt');
if ($r==true) {
//file locked - we can edit it
$canleave = true;
} else {
// I need a way to wait 100ms.
wait(100);
};
};
edit_file('file.txt'); // do what I want
unlock_file('file.txt');
?>
Help appreciated!
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Did you read the documentation? It has examples; start there. That will give you something more specific to ask about.
 

vv.bbcc19

Community Advocate
Community Support
Messages
1,524
Reaction score
92
Points
48
you need to know the locking files with flock()
The key problem with file system operations is the precarious situation you are in if two scripts attempt to write to a file at the same time. The fopen() function, when called on a file, does not stop that same file from being opened by another script, which means you might find one script reading from a file as another is writing, or, worse, two scripts writing to the same file simultaneously.

The solution to this problem is to use file locking, which is implemented in PHP using the flock() function. When you lock a file, you have the option of marking it a read-only lock, thereby sharing access to the file with other processes, or an exclusive lock, allowing you to make changes to the file. On Unix, flock() is advisory , meaning that the OS is free to ignore it. On Windows, flock() is mandatory, meaning that files are locked by the OS whether you ask for it or not!

The flock() function takes a file handle as its first parameter, and a lock operation as its second parameter. File handles you know already, and the operations are simple: LOCK_SH requests a shared lock, LOCK_EX requests an exclusive lock, and LOCK_UN releases a lock. Calling flock() will return true if the file lock was retrieved successfully, or false if it failed. So, for example, flock() could be used like this:
<?php
PHP:
<?php
    $fp = fopen( $filename,"w"); // open it for WRITING ("w")
    if (flock($fp, LOCK_EX)) {
        // do your file writes here
        flock($fp, LOCK_UN); // unlock the file
    } else {
        // flock() returned false, no lock obtained
        print "Could not lock $filename!\n";
    }
?>
File locking requires a fairly modern file system, such as NTFS (Windows), ext3/ext4 (Linux) and HFS+ (Mac). Furthermore, the Network File System (NFS), commonly used to provide file sharing across Unix boxes, is not suitable for use with flock().

The file locking mechanism in PHP automatically makes processes queue up for their locks by default. For example, save this next script as flock.php:
PHP:
<?php
    $fp = fopen("foo.txt", "w");
    if (flock($fp, LOCK_EX)) {
        print "Got lock!\n";
        sleep(10);
        flock($fp, LOCK_UN);
    }
?>
That script attempts to lock the file foo.txt, so you will need to create that file. The script locks it with LOCK_EX, which means no other program can lock that file. Once the lock is obtained, the script sleeps for ten seconds, then unlocks the file and quits. If a lock cannot be obtained because another application has a lock, the script waits at the flock() call for the lock to be released, then locks it itself and continues.

To test this out, open up two command prompts and run the script twice. The first script run will get a lock immediately and print "Got lock!", then sleep for ten seconds. If while the first script is sleeping you launch the second script, it will wait ("block") on the flock() call and wait for the first script to finish. When the first script finishes, the second script will succeed in getting its lock, print out "Got lock!" then sleep for ten more seconds until it finally terminates.

Sometimes it is not desirable to have your scripts wait for a file to become unlocked, and in this situation you can add an extra option to the second parameter using the bitwise OR operator, |. If you pass in LOCK_NB ORed with your normal second parameter, PHP will not block when it requests a file lock. This means that if the file lock is not available, flock() will return immediately with false rather than hang around waiting for a lock to become available.

Here is how that looks in code:
PHP:
<?php
    $fp = fopen("foo.txt", "w");
    if (flock($fp, LOCK_EX | LOCK_NB)) {
        echo "Got lock!\n";
        sleep(10);
        flock($fp, LOCK_UN);
    } else {
        print "Could not get lock!\n";
    }
?>
This time, the first script will get the lock and print "Got lock!", whereas the second will fail to get the lock, return immediately, and print "Could not get lock!"
 
Top