2015-01-12 2 views
1

Я создал простую безрезультатную CMS. При сохранении файла PHP открывает соответствующий файл, добавляет новые данные и закрывает файл (используя file_put_contents).PHP - предотвратить перезапись данных в файле

Все это хорошо работает - до тех пор, пока тот же файл не будет сохранен дважды (или более) одновременно. Под этим я подразумеваю, когда функция file_put_contents запускается в файле, который уже испытывает другую функцию file_put_contents. В этом случае в файл сохраняются только изменения для второго файла file_put_contents.

Итак, мой вопрос: есть ли способ проверить, записывается ли файл и ожидает ли он его записи, прежде чем запускать второй файл__процесса?

+1

Из любопытства почему бы не использовать базу данных? На ваш вопрос я думаю, что эта функция может помочь вам 'filectime()' – Daan

+0

То, что вы хотите, безусловно, возможно, но серьезно использовать базу данных. – PeeHaa

+0

вы можете использовать 'flock' для блокировки файла. – vaso123

ответ

1

Да, LOCK_EX Поддержка была добавлена ​​в file_put_contents в PHP 5.1, которая будет ждать, пока какая-либо другая блокировка файла не будет выпущена до ее написания. Вы можете легко проверить это самостоятельно.

lock.php

#!/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); 

put.php

#!/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 в оболочке два, и вы увидите, что она ждет, потому что для этого скрипта была создана уникальная блокировка записи. Теперь вернитесь к shell one и нажмите Ctrl + c, чтобы прервать выполнение (вы можете закрыть оболочку) и вернуться к своей второй оболочке. Он должен вывести foo, и скрипт должен завершиться.

Важно

Чтение файла не заблокирован для этого файла, если это использование требование flock, поскольку он поддерживает все операции (LOCK_SH | LOCK_EX).

SQLite

PDO SQLite даст вам возможность работать с простыми текстовыми файлами в качестве базы данных и заботиться о проблемах, как замок для вас. Если вам нужно работать с большим количеством файлов, и данные рассматривают его использование, поскольку оно содержит все, что вам нужно из коробки.

+0

Спасибо, это похоже на то, что я искал. Однако в этом примере один сценарий блокирует файл, а другой пытается записать его. Как я могу адаптировать это, чтобы один и тот же сценарий блокировал файл во время записи?Я пробовал несколько вещей, но ничего не работало. – rwacarter

+1

То же самое происходит, если вы запускаете один и тот же сценарий несколько раз, но не забывайте, что эти скрипты очень быстрые, вам нужно написать ** много ** данных, чтобы наблюдать за блокировкой. Вы можете попробовать следующую строку: 'file_put_contents (" lock.txt ", openssl_random_pseudo_bytes (1e9), LOCK_EX);' Это генерирует 1 ГБ случайных данных и записывает их в файл. Просто начните их почти в одно и то же время и, ну, подождите. :П – Fleshgrinder

Смежные вопросы