phpな休日 BBS sitemap
1. 複数行データの読み書き表示

データを蓄積するには複数行にして保存します。FORMからデータが送られて来たら最上部に1行追加していきます。ちょうどカード型データベースの1枚が1行に相当します。
POSTの受け取り方は前回と同様で、ログファイルを開くのに file関数を使用しました。file関数はファイルを開くと同時にデータを1行づつ配列に読み込んでくれるので便利です。
初出(複数行処理)の部分を赤字で記してみました。

<?php
mb_language("ja");
mb_internal_encoding("UTF-8");
if (($_POST["name"] != "") or ($_POST["comment"] != "")) { //もしPOSTに [name] か [comment] があれば
if (isset($_POST["name"])) { //もしPOSTに [name] があれば
$name = $_POST["name"]; //POSTのデータを変数$nameに格納
$name = htmlspecialchars ($name); //HTMLタグ禁止
$name = mb_strimwidth ($name, 0, 30, "", "UTF-8"); //長いデータを30バイトでカット
}
if (isset($_POST["comment"])) { //もしPOSTに [comment] があれば
$comment = $_POST["comment"]; //POSTのデータを変数$commentに格納
$comment = htmlspecialchars ($comment); //HTMLタグ禁止
$comment = mb_strimwidth ($comment, 0, 200, "", "UTF-8"); //長いデータを200バイトでカット
}
$time = date("Y/n/j G:i"); //日時の取得
$log = file("./log.txt"); //ファイル1行づつ配列に入れながら読み込む
$topwrite = "$name<>$comment<>$time<>¥n"; //新しく追加するデータを <> で区切って整形
$write = fopen("./log.txt","w"); //書き込み用モードでデータを開く(データは空になる)
flock($write, LOCK_EX); //ファイルロック開始
fputs($write, $topwrite); //先頭に1行書き込む
for($i = 0; $i < count($log); $i++){ //最後まで走査して
fputs($write, $log[$i]); //今までの分を書き込む
}
flock ($write, LOCK_UN); //ファイルロック解除
fclose ($write); //ファイルを閉じる
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>複数行読み書き表示</title>
</head>
<body>
<br>
<form method="POST" action="form3.php">
お名前 <input type="text" name="name" size="20"><br>
コメント <input type="text" name="comment" size="60"><br>
<input type="submit" value="送信">
</form>
<br>
<?php
$log = file("log.txt"); //データをオープン
for($i=0; $i<count($log); $i++) { //1行づつ走査しながら表示します
$list = explode("<>",$log[$i]);
print "お名前: " . $list[0] . "<br>¥n";
print "コメント: " . $list[1] . "<br>¥n";
print "日時: " . $list[2] . "<br>¥n";
print "<hr>";
}
?>
</body>
</html>

file関数でデータを全て読み込んでおき、fopenで空になったログファイルに新しい1行と今までのデータを書き込んでいきます。 表示時は for関数で1行づつ読み込んだデータを区切り文字 <> で区切って配列ごとに表示しています。それをファイルの終端まで繰り返します。

2. 古いデータを削除してログデータを一定行に保つ

WEB上で誰でも書き込めるフォームを設置する場合データが増えていきますので、古いデータから順に消去していく処理を付加します。 23行目の
for($i = 0; $i < count($log); $i++){

for($i = 0; $i < 4; $i++){
に書き換えると、常に5行残して古い行から捨てられます。

<?php
mb_language("ja");
mb_internal_encoding("UTF-8");
if (($_POST["name"] != "") or ($_POST["comment"] != "")) { //もしPOSTに [name] か [comment] があれば
if (isset($_POST["name"])) { //もしPOSTに [name] があれば
$name = $_POST["name"]; //POSTのデータを変数$nameに格納
$name = htmlspecialchars ($name); //HTMLタグ禁止
$name = mb_strimwidth ($name, 0, 30, "", "UTF-8"); //長いデータを30バイトでカット
}
if (isset($_POST["comment"])) { //もしPOSTに [comment] があれば
$comment = $_POST["comment"]; //POSTのデータを変数$commentに格納
$comment = mb_strimwidth ($comment, 0, 200, "", "UTF-8"); //長いデータを200バイトでカット
$comment = htmlspecialchars ($comment); //HTMLタグ禁止
}
$time = date("Y/n/j G:i"); //日時の取得
$log = file("./log.txt"); //ファイル1行づつ配列に入れながら読み込む
$topwrite = "$name<>$comment<>$time<>¥n"; //新しく追加するデータを <> で区切って整形
$write = fopen("./log.txt","w"); //書き込み用モードでデータを開く(データは空になる)
flock($write, LOCK_EX); //ファイルロック開始
fputs($write, $topwrite); //先頭に1行書き込む
for($i = 0; $i < 4; $i++){ //4行まで走査処理をする
fputs($write, $log[$i]); //今までの分を書き込む
}
flock ($write, LOCK_UN); //ファイルロック解除
fclose ($write); //ファイルを閉じる
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>複数行読み書き表示</title>
</head>
<body>
<br>
<form method="POST" action="form3.php">
お名前 <input type="text" name="name" size="20"><br>
コメント <input type="text" name="comment" size="60"><br>
<input type="submit" value="送信">
</form>
<br>
<?php
$log = file("log.txt"); //データをオープン
for($i=0; $i<count($log); $i++) { //1行づつ走査しながら表示します
$list = explode("<>",$log[$i]);
print "お名前: " . $list[0] . "<br>¥n";
print "コメント: " . $list[1] . "<br>¥n";
print "日時: " . $list[2] . "<br>¥n";
print "<hr>";
}
?>
</body>
</html>

サブウィンドウで実行
3. データを照合して2重投稿を防ぐ

さらにこのままではまったく同じ内容の送信を受け付けてしまいますので、送信があった場合 fgets でデータの最上行を読み込んでPOSTされた値と比較する処理を加えます。
if の処理が複雑になってきますが、図で表すと以下のようになります。

<?php
mb_language("ja");
mb_internal_encoding("UTF-8");
if (($_POST["name"] != "") or ($_POST["comment"] != "")) { //もしPOSTに [name] か [comment] があれば
if (isset($_POST["name"])) { //もしPOSTに [name] があれば
$name = $_POST["name"]; //POSTのデータを変数$nameに格納
$name = htmlspecialchars ($name); //HTMLタグ禁止
$name = mb_strimwidth ($name, 0, 30, "", "UTF-8"); //長いデータを30バイトでカット
}
if (isset($_POST["comment"])) { //もしPOSTに [comment] があれば
$comment = $_POST["comment"]; //POSTのデータを変数$commentに格納
$comment = mb_strimwidth ($comment, 0, 200, "", "UTF-8"); //長いデータを200バイトでカット
$comment = htmlspecialchars ($comment); //HTMLタグ禁止
}
$data = fopen ("./log2.txt","r"); //ファイルを読みこみ専用でオープン
$bdata = fgets ($data); //1行読み込む
list($bname,$bcomment,$btime) = explode("<>",$bdata); //変数に変換
fclose($data); //ファイルを閉じる
if (($bname != $name) or ($bcomment != $comment)){ // name か comment が違っていれば
$time = date("Y/n/j G:i"); //日時の取得
$log = file("./log2.txt"); //ファイル1行づつ配列に入れながら読み込む
$topwrite = "$name<>$comment<>$time<>¥n"; //新しく追加するデータを <> で区切って整形
$write = fopen("./log2.txt","w"); //書き込み用モードでデータを開く(データは空になる)
flock($write, LOCK_EX); //ファイルロック開始
fputs($write, $topwrite); //先頭に1行書き込む
for($i = 0; $i < 4; $i++){ //4行まで走査処理をする
fputs($write, $log[$i]); //今までの分を書き込む
}
flock ($write, LOCK_UN); //ファイルロック解除
fclose ($write); //ファイルを閉じる
}
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>複数行読み書き表示</title>
</head>
<body>
<br>
<form method="POST" action="form3.php">
お名前 <input type="text" name="name" size="20"><br>
コメント <input type="text" name="comment" size="60"><br>
<input type="submit" value="送信">
</form>
<br>
<?php
$log = file("log2.txt"); //データをオープン
for($i=0; $i<count($log); $i++) { //1行づつ走査しながら表示します
$list = explode("<>",$log[$i]);
print "お名前: " . $list[0] . "<br>¥n";
print "コメント: " . $list[1] . "<br>¥n";
print "日時: " . $list[2] . "<br>¥n";
print "<hr>";
}
?>
</body>
</html>

赤文字が新しく書き加えた部分です。

サブウィンドウで実行
2022.9.20 last edit

Produced by haku