Я создал простую CMS без базы данных. При сохранении файла PHP открывает соответствующий файл, добавляет новые данные и закрывает файл (используя file_put_contents).
Все это работает хорошо — пока один и тот же файл не будет сохранен дважды (или более) одновременно. Под этим я подразумеваю, когда функция file_put_contents запускается для файла, который уже испытывает другую функцию file_put_contents. В этом случае только изменения для второго файла file_put_contents сохраняются в файл.
Итак, мой вопрос — есть ли способ проверить, что файл уже записывается, и ждать, пока он не завершится, перед запуском второго file_put_contents?
Да, LOCK_EX
поддержка была добавлена file_put_contents
в PHP 5.1, который будет ждать, пока не будет снята любая другая блокировка файла, прежде чем записывать в него файл. Вы можете легко проверить это самостоятельно.
#!/usr/bin/env php
<?php
$h = fopen(__DIR__ . DIRECTORY_SEPARATOR . "lock.txt", "c");
register_shutdown_function(function () use ($h) {
fclose($h);
});
flock($h, LOCK_EX);
while (true);
#!/usr/bin/env php
<?php
$f = __DIR__ . DIRECTORY_SEPARATOR . "lock.txt";
file_put_contents($f, "foo", LOCK_EX);
echo file_get_contents($f) , PHP_EOL;
Поместите оба скрипта в один каталог и откройте две оболочки. казнить lock.php
в оболочке один и держать его открытым, выполнить put.php
во второй оболочке вы увидите, что он ждет, потому что другой скрипт для файла установил исключительную блокировку записи. Теперь вернитесь к первой и нажмите Ctrl + с чтобы прервать выполнение (вы можете закрыть оболочку) и вернуться к своей второй оболочке. Должен вывести foo
и скрипт должен завершиться.
Чтение файла не заблокировано для этого файла, если это требование использования flock
так как он поддерживает все операции (LOCK_SH | LOCK_EX
).
PDO SQLite даст вам возможность работать с простыми текстовыми файлами в качестве базы данных и решать такие проблемы, как блокировка для вас. Если вам нужно работать с большим количеством файлов и данных, рассмотрите возможность его использования, поскольку в нем есть все, что вам нужно, из коробки.
Других решений пока нет …