アプリ版:「スタンプのみでお礼する」機能のリリースについて

PHPの勉強として掲示板を作成しているのですが、謎の二重書き込みに出会い躓いています。
下記はテストとして書いた、状況が再現されるソースです。

<?php
$filename = './test.dat';
if($_REQUEST) {
$data = file($filename);
$newdata = "{$_REQUEST['newdata']}\n";

$logfile = @fopen($filename, "r+");
flock($logfile, LOCK_EX);
foreach($data as $value) {
fputs($logfile, $value);
}
fputs($logfile, $newdata);
flock($logfile, LOCK_UN);
fclose($logfile);
}
?>
<html>
<head><title>TEST</title></head>
<body>
<form action="test.php">
<input type="text" name="newdata">
<input type="submit">
</form>
</body>
</html>



5、6行目で

$newdata = "{$_REQUEST['newdata']}\n";
$data[] = $newdata;

とした場合、DATを逆順にして

$newdata = $_REQUEST['newdata'];
$array_unshift = $newdata;

とした場合、また、そこで追加せずに書き込み処理を

$logfile = @fopen($filename, "r+");
while(!feof($logfile)) {
$data[] = fgets($logfile);
}
fputs($logfile,$newdata);
foreach($data as $value) {
fputs($logfile, $value);
}

とした場合、など…どうやってもなぜか同じ症状が出ます。
しかももっと不思議なのは、どこでおかしくなっているのか調べようと思い途中にprint_r($data)を入れると、場所によってはなぜか二重書き込みが起きなかったりするのです。
検索しても同じ状況は見つけられずどうしたものかと悩んでおります。
情報が足りないかもしれませんが、何か気づいた方がいましたら教えてください。よろしくお願いします。

A 回答 (3件)

if($_REQUEST)の所為でページにアクセスした時点でfopen以下の処理が実行されてしまっている→2重処理


(これはログファイルをテキストエディタか何かで開いたまま実行すると確認できます)

入れる場所によっては~の下りはfputsの前後で結果が変わっているのでは?


解決方法はPOSTメソッドに変更するのが手っ取り早いです。
送信されるまで実行されないので2重処理もされません。

<form action="test.php" method="post">
<input type="text" name="newdata">
<input type="submit">


if($_POST) {
$data = file($filename);
$newdata = "{$_POST['newdata']}\n";
    • good
    • 0
この回答へのお礼

if($_REQUEST)やmethod="get"がいけないなんて思いもしませんでした(お恥ずかしい)。『形になるまではパラメータが見えている方が分かりやすい』なんて考えた罰ですね。

>fputsの前後で
まさにそうです。情報を出し忘れていてすみません。

cyanberryさんの場合は偶然だったのかが気になりますが、解決したので締め切らせていただきます。
お三方ありがとうございました。

お礼日時:2010/05/25 18:17

No1さんの指摘もその通りなのですが、試しにソースそのままをコピペして実行してみたら、別に2重書き込みになりませんでしたよ。


このソースとは違うものが動いてませんか?

この回答への補足

回答ありがとうございます。
試しに新しいディレクトリにこのtest.phpとtest.datだけを入れて実行したのですがやはり二重になりました。
本当に質問文に載せた分しかないファイルでアップロードしているので、何がcyanberryさんと違うのかまったく見当が付きません。
回答いただいたのにすみません。

補足日時:2010/05/25 15:58
    • good
    • 0
この回答へのお礼

回答ありがとうございました。またご縁がありましたらよろしくお願いします。コピペにて失礼ですが改めてお礼いたします。

お礼日時:2010/05/25 18:34


これって追加書き込みしたいんですか?
それとも新規ラインを追加した新しいファイルをつくるんですか?
@fopen($filename, "r+");

@fopen($filename, "a");
なのでは?
あと、エラー処理をスキップしているので、受け取りハンドルは厳密にしたほうがいいとおもいます。
今のを整理すると、
先読みの部分は使いません。(必要すらない)
function hoge() {
-> $filename = './test.dat';
-> if($_REQUEST) {
-> -> $logfile = @fopen($filename, "a");
-> -> -> fputs($logfile, $newdata);
-> -> fclose($logfile);
-> }
}
こんだけで全部終わるんですが、だめですか?

この回答への補足

回答ありがとうございます。追加書き込みです。
書き忘れてしまったんですが、"a"とか一度中身を全部配列に入れてから"w"で開いて書き込みとかも実はやりました。やはり二重になってしまいます。
ちなみにもうひとつ書き忘れていたのが、test.phpはこのスクリプト自体ということです。
教えていただいた記述をコピーして実行しましたが、やはり二重になってしまいました。せっかく解答していただいたのにすみません。

補足日時:2010/05/25 15:53
    • good
    • 0
この回答へのお礼

回答ありがとうございました。またご縁がありましたらよろしくお願いします。コピペにて失礼ですが改めてお礼いたします。

お礼日時:2010/05/25 18:34

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!