PHP заблокировать текстовый файл для редактирования?

У меня есть форма, которая записывает свой ввод в текстовый файл. Можно ли заблокировать текстовый файл для редактирования и, возможно, дать дружеское сообщение "файл отредактирован другим пользователем, повторите попытку позже".

Я хотел бы избежать конфликтов, если файл имеет несколько редакторов одновременно.

Вот как в данный момент добавляется запись.

$ content = file_get_contents ("./ file.csv");
$ fh = fopen ("./ file.csv", "w");
fwrite ($ fh, $ date_yy. '-'. $ date_mm. '-'. $ date_dd. '|'. $ address. '|'. $ person. '|'. $ time_hh. ':'. $ time_mm);
fwrite ($ fh, "\ n". $ content);
fclose ($ ФХ);

Какие-нибудь мысли?

5 ответов

Ты можешь использовать flock() функция для блокировки файла. Для больше см. Это

Что-то вроде:

   <?php

      $content = file_get_contents("./file.csv");
      $fp = fopen("./file.csv", "w"); // open it for WRITING ("w")
      if (flock($fp, LOCK_EX)) 
      {
      // do your file writes here
      fwrite($fh, $date_yy . '-' . $date_mm . '-' . $date_dd . '|' . $address . '|' .  $person . '|' . $time_hh . ':' . $time_mm);
      fwrite($fh, "\n" . $content);
      fclose($fh);
      flock($fh, LOCK_UN); // unlock the file
      } 
   ?> 

В порядке желательности:

  1. Используйте базу данных.
  2. Используйте более одного текстового файла.
  3. Используйте замки:

например:

$lockwait = 2;       // seconds to wait for lock
$waittime = 250000;  // microseconds to wait between lock attempts
// 2s / 250000us = 8 attempts.
$myfile = '/path/to/file.txt';

if( $fh = fopen($myfile, 'a') ) {
  $waitsum = 0;
  // attempt to get exclusive, non-blocking lock
  $locked = flock($fh, LOCK_EX | LOCK_NB); 
  while( !$locked && ($waitsum <= $lockwait) ) {
    $waitsum += $waittime/1000000; // microseconds to seconds
    usleep($waittime);
    $locked = flock($fh, LOCK_EX | LOCK_NB);
  }
  if( !$locked ) {
    echo "Could not lock $myfile for write within $lockwait seconds.";
  } else {
    // write out your data here
    flock($fh, LOCK_UN);  // ALWAYS unlock
  }
  fclose($fh);            // ALWAYS close your file handle
} else {
  echo "Could not open $myfile";
  exit 1;
}

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

Лучше всего создать файл токена в том же каталоге, проверить его существование и сообщить об ошибке, если он существует.

Как и в любой схеме блокировки, у вас будут гоночные условия и блокировки, которые остаются после завершения операции, поэтому вам потребуется способ их устранения.

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

Если они разные, покажите ошибку.

Вы могли бы попробовать flock — Portable advisory file locking?

http://php.net/manual/en/function.flock.php

Я бы просто использовал простое число или что-то в этом роде.

  $content = file_get_contents("./file.csv");
  $fh = fopen("./file.csv", "w");
  $status = 1;

...      

if($status == 1){
   fwrite($fh, $date_yy . '-' . $date_mm . '-' . $date_dd . '|' . $address . '|' . $person . '|' . $time_hh . ':' . $time_mm);
   fwrite($fh, "\n" . $content);
   fclose($fh);
   $status = 0;
  }
else
     echo "the file is edited by another user, please try again later.";

Это то, что вы имели ввиду?

Другие вопросы по тегам