自作掲示板に投稿番号とパスワードを入力して投稿を削除できる機能を実装しようとしたのですがファイル内から投稿番号とパスワードを検索するところが上手くいきません。
ゴールはファイルの中からPOSTされた投稿番号とパスワードに一致する行を探して空白を挿入して削除することです。
現象としてはエラー文は出ず投稿番号欄とパスワード欄の文字が消えて他は何も変わらないといった状態です。
正規表現を使っているんですがどなたか助言をお願いします。
機能のところだけ載せようかと思ったのですが全体があった方がいいかと思い載せました。見づらくてすみません。
<?php
ini_set('display_errors', 1);
//アクセスカウンターの部分
$filename = 'counter.dat';
$fp1 = fopen($filename, "r+");
flock($fp1,LOCK_EX);
$count = fgets($fp1,32);
$count++;
fseek($fp1, 0);
fputs($fp1, $count);
flock($fp1, LOCK_UN);
fclose($fp1);
//ここまでアクセスカウンター
//定義系
$err_msg1 = "";
$err_msg2 = "";
$err_msg3 = "";
$message = "";
$name = (isset($_POST["name"]) === TRUE) ?$_POST["name"]:"";
$comment = (isset($_POST["comment"]) === TRUE) ?trim($_POST["comment"]):"";
$_POST["date"] = date('Y/m/d H:i:s');
$color = isset($_POST["color"]) ? $_POST["color"] : '';
$password = (isset($_POST["password"]) === TRUE) ?trim($_POST["password"]):"";
//ここまで定義系
//入力の判定と書き込み
if(isset($_POST["send"]) === TRUE){
if($name === "")$err_msg1 = '名前を入力してください';
if($comment === "")$err_msg2 = 'コメントを入力してください';
if($password === "" || mb_strlen($_POST["password"]) > 4 || !ctype_digit($_POST["password"]))
$err_msg3 = 'パスワードを4字以下の数字で設定してください';
if($err_msg1 === "" && $err_msg2 === "" && $err_msg3 ===""){
$fp2 = fopen("data.txt", "a+");
$file = file("data.txt");
$number = count($file)+1;
fwrite($fp2, $number."\t".$name."\t".$comment."\t".date('Y/m/d H:i:s')."\t".$color."\t".$password."\r\n");
fclose($fp2);
$message = '書き込みに成功しました';
}
}
//ここまでエラー文&ファイル書き込み
//ファイル読み込み
$fp3 = fopen("data.txt", "r");
$dataArr = array();
while($res = fgets($fp3)){
$tmp = explode("\t", $res);
$arr = array(
"number"=>$tmp[0],
"name"=>$tmp[1],
"comment"=>$tmp[2],
"date"=>$tmp[3],
"color"=>$tmp[4],
"password"=>$tmp[5]
);
$dataArr[] = $arr;
}
//ここまでファイル読み込み
//削除機能
if(isset($_POST["delete"]) === TRUE){
$fp4 = fopen("data.txt", "r+");
$file = file("data.txt");
$sakujo = $_POST["sakujo"];
$pass = $_POST["pass"];
$pattern = "/^($sakujo).($pass)$/";
if(preg_match($pattern, $file) === 1){
preg_replace($pattern, "", $file);
$message = '削除しました';
}else{
$message = '<font color="red">この投稿は削除できません</font>';
}
fclose($fp4);
}
//ここまで削除機能
$fp4 = fopen("data.txt", "r+");
$file = file("data.txt");
var_dump($file);
fclose($fp4);
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.ong/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>掲示板</title>
</head>
<body bgcolor="#9999FF">
<table border="1">
<tr><td><?php echo $count;?></td></tr>
</table>
<h1><center>一行掲示板</center></h1>
<h3><center>思いつくまま、一言メッセージをどうぞ。</center></h3>
<h5><center>パスワードを設定し自分の投稿を削除することができます。</center></h5>
<?php echo $message; ?>
<center><table border="2" bgcolor="#9999FF">
<form action="" method="POST">
<tr>
<td>名前</td><td><input type="text" name="name" value="<?php echo $name;?>"></td>
</tr>
<?php echo '<font color="red">'.$err_msg1.'</font>';?><br>
<tr>
<td>コメント</td><td><textarea name="comment" row="4" cols="40" value="<?php echo $comment;?>"></textarea></td>
</tr>
<?php echo '<font color="red">'.$err_msg2.'</font>';?><br>
<tr>
<td>
<label for="color">文字の色</label>
<select name="color">
<option value="#000000" selected>黒</option>
<option value="#FFFFFF">白</option>
<option value="#FF0000">赤</option>
<option value="#0000FF">青</option>
<option value="#00FF00">緑</option>
<option value="#660099">紫</option>
<option value="#FF3300">橙</option>
</select>
</td>
<td>パスワード<input type="password" name="password"></td>
<?php echo '<font color="red">'.$err_msg3.'</font>';?>
<td><input type="submit" name="send" value="クリック"></td>
</tr>
</form>
</table></center>
<br>
<hr>
<br>
<dl>
<?php foreach($dataArr as $data):?>
<p><span><?php
echo '['.$data["number"].']';
?></span>
<span>
<font color="<?php echo htmlspecialchars($data["color"], ENT_QUOTES, 'UTF-8');?>">
<?php echo htmlspecialchars($data["name"], ENT_QUOTES, 'UTF-8');?>
</font>
</span> > <span>
<font color="<?php echo htmlspecialchars($data["color"], ENT_QUOTES, 'UTF-8');?>">
<?php echo htmlspecialchars($data["comment"], ENT_QUOTES,'UTF-8');?>
</font>
</span>
<span>(<?php echo $data["date"];?>)</span>
</p>
<?php endforeach;?>
</dl>
<br>
<hr>
<br>
<center><table border="2" bgcolor="#9999FF">
<form action ="" method="POST">
<tr>
<td>投稿番号</td><td><input type="text" name="sakujo" required></td>
</tr>
<tr>
<td>パスワード</td><td><input type="password" name="pass" required></td>
</tr>
<tr><td></td>
<td><input type="submit" value="削除" name="delete"></td>
</tr>
</form></table></center>
</body>
</html>
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
いろいろ誤解されているソースに見えます。
まず、
$fp4 = fopen("data.txt", "r+");
$file = file("data.txt");
var_dump($file);
fclose($fp4);
このfopen()
とfclose()
は必要ありません。file()
で、内部でOpenとCloseを勝手にやってくれています。
次に、file()
で取り出した値は、ファイル内部のポインタをリアルタイムに保持しているわけではなく、単に書き込まれているデータと同じものを配列にブチ込んでいるだけです。
なので
$file = file("data.txt");
$file = null;
としても、ファイルの中身が空になるわけではありません。
やるとすると、$file
の中身を書き換えたあと、mode "w"でfopen()
し、中身をごっそり書き換えると言う形ですかね。
ただ、これだとほぼ同時にアクセスされている方がいるとデータが壊れる(失われる)可能性もありますので、おすすめできません。
普通はDBを使うべき案件ですが、あえてファイルでやるとすると、投稿1つずつを1ファイルに格納する方がいいと思います。
/data/post/001.txt /data/post/002.txt ・・・など
投稿が増えると管理が大変ですが、そのあたりは最初に読み込むのは10件までとするなどして制御していくしかないですね。
ちなみに、TAB区切りやカンマ区切りのデータの読み書きについてはfputcsv()
fgetcsv()
などの便利な関数もあります。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
正規表現に関しては
$pattern = "/^($sakujo)\t.+\t($pass)$/";
こんな感じでしょうか?
.
は任意の1文字にしかマッチしないので.+
として任意の文字列にマッチする必要があります。
また、 ($sakujo)\t
としておかないと
1\t(name1)\t(comment1)\t(date1)\t(color1)\t(password)
10\t(name2)\t(comment2)\t(date2)\t(color2)\t(password)
というような場合に 10のほうも検索に引っかかってしまいます。
最後の ($password)
側も同様に \t($password)
passwordが test
だった場合、このままだと t
でも削除できてしまいます。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
前回答者の内容を元に、「正規表現チェッカー」で、自分が望むチェックが出来ているか、調べながら試行錯誤するといいかもです。
http://okumocchi.jp/php/re.php
あと正規表現のマッチだけでは、該当ファイル行は消せないので、これも前回答者の内容通り、行ごと消したファイルを新たに一時的に作成しリネーム等するか、本ファイルを上書きするか、なりで、ロックを掛けて更新する必要がありますね。
投稿が同じタイミングだったので、前回答に便乗する形になってしまい、すみません。。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.33%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
m.ts10806
2018/07/10 14:45
「うまく動作しない」「うまくいかない」では何が起きているか伝わりません。「○○のようになるはずなのに××となってしまう」のような形で「ゴール」と「現象(エラーメッセージなども含む)」を明確にしてください。https://teratail.com/help/question-tips#questionTips3-4-1
naberius
2018/07/10 14:51
ゴールはファイルの中からPOSTされた投稿番号とパスワードに一致する行を探して空白を挿入して削除することです。現象としてはエラー文は出ず投稿番号欄とパスワード欄の文字が消えて他は何も変わらないといった状態です。わかりづらくてすみません。