Как я могу использовать file_put_contents() с FILE_APPEND | Безопасность LOCK_EX?

Я использую:

file_put_contents("peopleList.txt", $person, FILE_APPEND | LOCK_EX);

для записи в конец файла и для того, чтобы никто другой (или скрипт) не выполнял запись в тот же файл одновременно.

В руководстве по PHP говорится, что в случае неудачи он вернет ложное значение.

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

Возможно, зацикливание функции в цикле while до тех пор, пока она не вернет false (съежится), или просто предоставление пользователю (посетителю веб-сайта) какого-либо графического интерфейса, запрашивающего повторную попытку?


person hozza    schedule 19.01.2012    source источник
comment
Apache порождает поток, в котором выполняется процесс PHP. Несколько пользователей = несколько процессов PHP. Только процесс, получивший блокировку, может работать с файлом. Все остальные процессы получат сообщение об ошибке от функции file_put_contents, а file_put_contents, выданный этими пользователями, ничего не запишет в файл. Это означает, что пока 1 пользователь пишет, другим будет отказано, и функция вернет логическое значение false.   -  person Mjh    schedule 19.01.2012
comment
Причина существования LOCK_EX — это совсем другая тема. Если вы все равно хотите писать в файл, просто удалите LOCK_EX, так как он вам не нужен, и последний человек, который получит доступ к вашему веб-сайту/скрипту, будет тем, кому будут записаны данные в файл. Кроме того, поскольку вы делаете добавление - какой смысл вообще блокировать файл? Просто удалите его.   -  person Mjh    schedule 19.01.2012
comment
Я использую LOCK_EX и FILE_APPEND вместе, потому что другие сценарии имеют возможность записывать в файл, и я не делаю то, что они могут делать, пока к нему добавляются данные, и наоборот.   -  person hozza    schedule 19.01.2012
comment
Все ли сценарии добавляют данные в файл?   -  person Mjh    schedule 19.01.2012
comment
Нет, некоторые будут перезаписаны, а некоторые просто прочитаны.   -  person hozza    schedule 19.01.2012
comment
Если вам действительно нужна блокировка файла для записи в его конец, может быть лучше хранить эти данные в mysql и просто делать каждую новую запись новой строкой и объединять записи в один документ. Таким образом, у вас не будет ошибок блокировки. Но я тоже отвечу на вопрос.   -  person WojonsTech    schedule 25.01.2012


Ответы (2)


На самом деле, мой предыдущий ответ был немного устаревшим. flock() блокирует до тех пор, пока не будет получена запрошенная блокировка:

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

Так что, поскольку file_get_contents() использует его, я предполагаю, что это то же самое. Тем не менее, имейте в виду, что это зависит от операционной системы.

Что еще более важно, вам не нужно блокировать файл в описанном вами сценарии по причинам N.B. уже объяснил. Если вы не используете CLI SAPI, я не могу придумать общий сценарий, в котором вы должны беспокоиться о блокировке файлов.

person yannis    schedule 19.01.2012
comment
@hozza, пожалуйста, не нужно гадать, о чем я думаю, я просто объясняю. Если вы их не понимаете, это другое дело. Использование цикла в связке со сном попросту говоря — глупо. Вы делаете FILE_APPEND, нет необходимости использовать LOCK_EX вообще. Не копируйте примеры с php.net вслепую, там написано что к чему и для чего. - person Mjh; 19.01.2012
comment
Код, который я предоставил, является примером. Сценарий - это просто множество сценариев, которые могут добавлять, усекать, записывать или читать файл. Я хочу, чтобы одна из этих вещей происходила одновременно, поэтому я хочу заблокировать файл с помощью LOCK_EX при использовании file_put_contents(); - person hozza; 19.01.2012
comment
Тогда что сказал @NB. Попробуйте запустить параллельные сценарии и посмотрите, что произойдет - person yannis; 19.01.2012

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

if ($result === false) { print "failed to lock"; }

Теперь, если вы хотите попытаться получить блокировку несколько раз, просто используйте цикл, чтобы продолжать попытки записи в файл.

person WojonsTech    schedule 25.01.2012