サーバー・サイドの場合、多数のユーザーが同時にアクセスした場合を考慮する必要があります。
具体的にはサーバー・サイドの場合は、ファイル出力時にファイルをロックしないとデータ破壊される危険性があります。
また ファイルの書き換え(ファイル入力してファイル出力する)は、ファイル入出力を一体としてロックしないとデータ破壊される危険性があります、つまり ファイル入力とファイル出力でflockを2つに分けるとファイル・データが破壊される危険性があります。
下記デモでもファイル入力とファイル出力でflockは1つだけだと言うことに注意して下さい。
なお (データの削除などで)ファイル・サイズが前より小さくなる場合は「rewind(~)、ftruncate(~,0)」で一旦ファイル・サイズをゼロにする必要があります。
$delimiterは"\t"タブ文字が推奨されますが、デバッグ用表示には"<>"の方が分かりやすいでしょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
<?php
$delimiter = "<>"; // "\t"; //
$fname_sample = "sample.txt";
$sPQ_Name = "";
if (isset($_POST['name'])) {
$sPQ_Name = $_POST['name'];
echo "sPQ_Name: {$sPQ_Name}<br>";
}
$sPQ_Comment = "";
if (isset($_POST['comment'])) {
$sPQ_Comment = $_POST['comment'];
echo "sPQ_Comment: {$sPQ_Comment}<br>";
}
// echo "POST['name']: {$_POST['name']}<br>";
// echo "POST['comment']: {$_POST['comment']}<br>";
$sHV_Name = "";
$sHV_Comment = "";
$sSubmit_Add = null;
if ($sPQ_Name && $sPQ_Comment) {
echo "if (sPQ_Name && sPQ_Comment)<br>";
if (isset($_POST['submit_add'])) {
$sSubmit_Add = $_POST['submit_add'];
}
} else {
echo "else (sPQ_Name && sPQ_Comment)<br>";
$sHV_Name = $sPQ_Name;
$sHV_Comment = $sPQ_Comment;
}
echo "sSubmit_Add: {$sSubmit_Add}<br>";
// ヒアドキュメント
echo <<<EOT
<form action="" method="POST">
<input type="text" name="name" value="{$sHV_Name}" placeholder="名前"><br>
<input type="text" name="comment" value="{$sHV_Comment}" placeholder="コメント" >
<input type="submit" name="submit_add" value="送信"><br>
<input type="text" name="deleteNo" value="" placeholder="削除対象番号">
<input type="submit" name="submit_del" value="削除">
</form>
EOT;
echo "ファイル入力<br>";
touch($fname_sample);
($fhrp_sample = fopen($fname_sample, "r+"))
|| die("die: fopen r+: {$fname_sample}.");
flock($fhrp_sample, LOCK_EX); // ファイル排他ロック
// LOCK_SH : ファイル共有ロック
// LOCK_EX : ファイル排他ロック
$sample_summary = [];
$num = 0;
$index = 0;
while ($line = fgets($fhrp_sample)) {
$line = str_replace(PHP_EOL, '', $line);
$sample_summary[] = $line;
$a1sCol = explode($delimiter, $line);
$n = intval($a1sCol[0]);
$num = max($num, $n);
echo "{$sample_summary[$index]}<br>";
$index++;
}
echo "<br>";
if ($sSubmit_Add) {
echo 'if($sSubmit_Add)' . "<br>";
$num++;
$line = "{$num}{$delimiter}{$_POST['name']}{$delimiter}{$_POST['comment']}";
$sample_summary[] = $line;
echo "{$sample_summary[$index]}<br>";
echo "<br>";
}
if (isset($_POST['submit_del'])) {
echo 'if(isset($_POST[submit_del]))' . "<br>";
$nDeleteNo = intval($_POST['deleteNo']);
$index = -1;
foreach ($sample_summary as $key => $line) {
$a1sCol = explode($delimiter, $line);
$num = intval($a1sCol[0]);
if ($nDeleteNo === $num) {
$index = $key;
echo "index={$index}<br>";
echo "{$line}<br>";
break;
}
}
if (0 <= $index) {
unset($sample_summary[$index]);
}
echo "<br>";
}
if ($sSubmit_Add || isset($_POST['submit_del'])) {
echo "ファイル出力<br>";
// fseek($fhrp_sample, 0)
rewind($fhrp_sample)
|| die("die: fseek: {$fname_sample}.");
ftruncate($fhrp_sample, 0)
|| die("die: ftruncate: {$fname_sample}.");
foreach ($sample_summary as $key => $line) {
echo "{$line}<br>";
fwrite($fhrp_sample, $line . PHP_EOL)
|| die("die: fwrite: {$fname_sample}.");
}
}
// ファイルclose // ファイル・ロックも開放
fclose($fhrp_sample)
|| die("die: fclose: {$fname_sample}.");
?>
</body>
</html>
|
|