How to lock a file using PHP
In this post, you will learn how to lock a file using the PHP programming language.
File locking is an important task. It restricts other users from changing a specific file. It allows only one user at a time to access or modify it. PHP provides the flock() method for portable advisory file locking. This was introduced with PHP version 4.0. This method provides options to mark the file for locking purposes. There are two kinds of locks we can make with flock- shared locks and exclusive locks. If you want to read only lock the file, use the shared lock, and if you want to lock the file for writing purposes, use the exclusive lock.
Syntax of flock()
flock($file_handler, $operation, $block)
$file_handler— It is a file handler pointer created by using fopen().
$operation— The lock operation can contain one of the following constants-
- LOCK_SH— It requests a shared lock (reader).
- LOCK_EX— It requests an exclusive lock (writer).
- LOCK_UN— It releases a lock either shared or exclusive.
- LOCK_NB— It avoids blocking other processes while locking.
The $block is optional, set to 1 to block other processes while locking. The flock() function returns a boolean value. It returns TRUE if the file lock is retrieved successfully and FALSE otherwise.
PHP flock() Exclusive lock (LOCK_EX) example
?php $php_errormsg = 'Error to lock a file.'; $write = 'Natural environment plays a great role in the existence of life on earth.'; $fh = fopen('test.txt','a') or die($php_errormsg); if( flock($fh,LOCK_EX) ) < fwrite($fh,$write) or die($php_errormsg); fflush($fh) or die($php_errormsg); flock($fh,LOCK_UN); >fclose($fh) or die($php_errormsg); ?>
In the above code, we have opened a file ‘text.txt‘ and assigned the file handler to $fh. Next, we lock the file using LOCK_EX (exclusive lock) in flock() function and write the $write variable to the file. The fflush() function flushes the output to the file. Finally, we released the locked file using LOCK_UN in the flock() function and closed the file handler. If you are using PHP version >= 5.3, you must manually unlock the file using the fclose() function.
When you execute the above code, it will append the given content at the end of the text file. Make sure to provide the write file path. If any error occurs during script execution, it will return the value provided in ‘$php_errormsg‘.
PHP flock() Shared lock (LOCK_SH) example
As you saw in the above example, we have a locked file for writing. Here you will know how to read a locked file.
?php $php_errormsg = 'Error to lock a file.'; $fh = fopen('test.txt','r+') or die($php_errormsg); if( flock($fh,LOCK_SH) ) < $content = fread($fh, 1000); echo $content; fclose($content); >?>
PHP flock() Non-blocking locking example
When the file is locked by another user, and you don’t want to block while locking, use LOCK_NB as a bitmask to LOCK_SH or LOCK_EX.
?php $php_errormsg = 'Error to lock a file.'; $fh = fopen('test.txt','w+') or die($php_errormsg); $wouldblock = null; if(flock($fh, LOCK_EX | LOCK_NB)) < fwrite($fh,'Write content here') or die($php_errormsg); fflush($fh) or die($php_errormsg); flock($fh,LOCK_UN); fclose($content); >else < echo 'File is currently locked by other user'; >?>
flock
flock() позволяет осуществить простую модель чтения/записи, которая может быть использована практически на любой платформе (включая большинство вариантов Unix и даже Windows).
В версиях PHP до 5.3.2 блокировка освобождалась также вызовом функции fclose() (которая также вызывается автоматически по завершении скрипта).
PHP поддерживает портируемый способ консультативной блокировки (adviosory locking) полностью всего файла (что означает, что все программы, осуществляющие доступ к файлу, должны использовать один и тот же способ блокировки, иначе блокировка не будет работать). По умолчанию, данная функция будет ждать получения блокировки; это поведение можно изменить с помощью описанного ниже параметра LOCK_NB .
Список параметров
Указатель ( resource ) на файл, обычно создаваемый с помощью функции fopen() .
- LOCK_SH для получения разделяемой блокировки (чтение).
- LOCK_EX для получения эксклюзивной блокировки (запись).
- LOCK_UN для снятия блокировки (разделяемой или эксклюзивной).
Также возможно добавить константу LOCK_NB в качестве битовой маски к любой из вышеуказанных операций, если вы не хотите ждать пока flock() получит блокировку.
Необязательный третий параметр будет установлен в 1, если блокировка будет блокирующей (код ошибки EWOULDBLOCK). (не поддерживается на Windows)
Возвращаемые значения
Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.
Список изменений
Версия | Описание |
---|---|
5.3.2 | Автоматическое снятие блокировки при закрытии было удалено. Снятие блокировки теперь всегда должно осуществляться вручную. |
Примеры
Пример #1 Пример использования функции flock()
if ( flock ( $fp , LOCK_EX )) < // выполняем эксклюзивную блокировку
ftruncate ( $fp , 0 ); // очищаем файл
fwrite ( $fp , «Что-нибудь пишем сюда\n» );
fflush ( $fp ); // очищаем вывод перед отменой блокировки
flock ( $fp , LOCK_UN ); // отпираем файл
> else echo «Не удалось получить блокировку !» ;
>
Пример #2 Использование flock() с параметром LOCK_NB
/* Включаем параметр LOCK_NB в операции LOCK_EX */
if(! flock ( $fp , LOCK_EX | LOCK_NB )) echo ‘Не удалось получить блокировку’ ;
exit(- 1 );
>
Примечания
Замечание:
В Windows flock() использует обязательную (mandatory) блокировку вместо консультативной. Обязательная блокировка также поддерживается на Linux и операционных системах, основанных на System V с помощью стандартного механизма, который предоставляет системный вызов fcntl(): т.е. искомый файл должен иметь установленный бит доступа setgid и неустановленный бит группового выполнения. Для корректной работы этой схемы в Linux, файловая система также должна быть смонтирована с опцией mand.
Замечание:
Из-за того, что функции flock() необходим указатель на файл, вам может понадобиться воспользоваться специальным запирающим файлом для того, чтобы ограничить доступ к файлу, который вы намерены очищать, путём его открытия в режиме записи (используя «w» или «w+» в качестве аргумента функции fopen() ).
Замечание:
Может быть использована только на дескрипторах локальных файлов, возвращенных функцией fopen() , или файловых дескрипторах пользовательских потоков, реализующих метод streamWrapper::stream_lock() .
Присвоение другого значения аргументу handle в последующем коде отменит существующую блокировку.
В некоторых операционных системах flock() реализован на уровне процессов. При использовании многопоточных серверных API, таких как ISAPI, вы не можете полагаться на flock() для защиты ваших файлов от других PHP-скриптов, которые работают в параллельном потоке на том же сервере!
flock() не поддерживается на старых файловых системах вроде FAT и ее производных, так что всегда будет возвращать FALSE в этом окружении (это особенно касается пользователей Windows 98).
Php and lock file
Если наш веб-сайт посещает множество людей, которые одновременно обращаются к одному и тому же файлу, то мы можем столкнуться с некоторыми проблемами. В частности, при одновременной попытке записи несколькими пользователями файл может быть поврежден, либо выдать неожиданные результаты, если один человек считывает файл, а другой одновременно записывает его. Возникает проблема синхронизации доступа пользователей.
Чтобы ограничить доступ к файлу, в PHP используется функция flock() . Эта функция блокирует доступ к файлу, когда он уже занят одним пользователем, а все остальные запросы ставит в очередь. При освобождении файла он разблокируется, передается первому в очереди пользователю и снова блокируется.
Функция имеет следующее определение:
bool flock (resource $handle , int $operation [, int &$wouldblock ])
Первый параметр — дескриптор файла, возвращаемые функцией fopen() .
Второй параметр указывает на тип блокировки. Он может принимать следующие значения:
- LOCK_SH (или число 1): разделяемая блокировка (чтение файла)
- LOCK_EX (или число 2): исключительная блокировка (запись файла)
- LOCK_UN (или число 3): для снятия блокировки
- LOCK_NB (или число 4): эта константа используется только вместе с одной из предыдущих в битовой маске (LOCK_EX | LOCK_NB), если не надо ждать пока flock() получит блокировку
Третий необязательный параметр $wouldblock будет содержать true , если блокировка будет блокирующей.
При успешном выполнении функция flock возвратит значение true , а в случае ошибки — false .
Используем flock для ограничения доступа к файлу:
При изменении файла блокировка ставится непосредственно перед внесением изменений, а снимается сразу после их внесения. Иначе программа может замедлить свою работу. Поэтому вызов, блокирующий файл: flock($fd, LOCK_EX) поставлен непосредственно перед вызовом функции fwrite($fd, «$str») . А снятие блокировки с помощью константы LOCK_UN идет сразу после записи.
Обратите внимание, что при открытии файла здесь использовался режим ‘r+’, а не ‘w’ или ‘w+’, так как ‘w’ и ‘w+’ уже подразумевают изменение файла. Поэтому при блокировке, даже если надо делать запись, не рекомендуется использование ‘w’ и ‘w+’.
Если нам надо стереть все содержимое файла и перезаписать файл по-новому, то мы можем воспользоваться функцией ftruncate :
How to Lock File in PHP
While writing to files that are possibly being read by other scripts at the same time, you will run into problems at some point specifically when write is not totally be completed because another script is reading the same file. The reading script will only see a partial file at that moment.
To Prevent, this problem is not hard to do, and the method to prevent this problem is called locking. We can set locks on files with flock() function in PHP. If the file is locked with flock() function, it is prevented to read a script from reading a file when it is being written to by another script.
flock() allows the implementation of a simple platform that can be used for read/write any of the files. If the optional third argument is set to TRUE, the lock would block. Lock operation can release when call fclose() function called or code execution is completed.It will automatically release the lock. If successful it returns TRUE, on failure returns FALSE.
PHP support in a better way for locking so you have to use the common way to lock the file or it will not work. A portable method for locking all the files, You can use the flock () function. flock() function handle operation must be an open file pointer. the operation can be one of the following values:
Second and important parameter operation is for three kinds of possible locks.
- Shared lock(Reader)
- exclusive lock(Writer) :LOCK_EX acquire an exclusive lock on the file and blocks until this lock can be acquired.An exclusive lock will only be granted if there are no other locks on the file.
- Un lock After we write to the file, we can release the lock with flock($fp,LOCK_UN);
Let’s have a look with LOCK_EX option in flock() function: