phpな休日 BBS sitemap
1. 管理者削除

[ゲストブック] の時に作った [管理者削除] の機能を加えます。最初にフォームですが、[ゲストブック] の時は受け取り時の条件分岐に記事ナンバー(name="delno")の有無を使用しましたが、今回はひとつのフォームで [削除ナンバー]・[編集ナンバー] の送信を兼ねるようにしますので、分岐条件には submit につけた名前(name="delete")を使用します。

<form action="./index.php?page=20&no=1" method="POST">
no. <input size="4" name="delno"> pass <input type="password" size="10" name="pass"> <input type="submit" name="delete" value="管理者削除">
</form>

[ゲストブック] の時と違うのは記事に返信がついている場合があるので、スレッドごとの削除にします。
手法は前回の [返信投稿時の処理] の 2. 返信投稿があったスレッドをログの先頭に上げる で行った処理と同様で最後の merge を省略するだけです。

if (isset($_POST["delete"])) { //削除の場合
$pass = $_POST["pass"]; //POSTの値を受け取って変数に割り当てる
$delno = $_POST["delno"]; //POSTの値を受け取って変数に割り当てる
if ($pass == "password") { //パスワードが正しければ
$data = file("./bbslog.cgi"); //ログファイルを開いて
$linecount = 0; //行数カウント
for ($i = 0; $i < count($data); $i++) { //走査する
$list = explode("<>", $data[$i]); //区切り文字 <> で区切る
if ($delno == $list[0]) { //$delnoを頼りに親記事を探す
$top = $i; //上からの行数
$linecount++; //行数をプラス
}
elseif ($delno == $list[1]) {
$linecount++; //行数をプラス
}
}
if (isset($linecount)) {
$string = array_splice($data, $top, $linecount); //同一スレッド行を削除
}
$deldata = fopen("./bbslog.cgi", "w"); //書き込みモードでファイルを開く
flock($deldata, LOCK_EX); //ファイルロック
foreach($data as $value) { //配列処理して
fputs($deldata, $value);} //書き込む
flock($deldata, LOCK_UN); //ファイルロック解除
fclose($deldata); //ファイルを閉じる
}
}

実行

返信記事がある場合、親記事・返信記事もろとも削除することになります。単独で削除したい場合は(削除ではなく) [管理者編集] のほうで対処しようと思います。

2. 管理者編集

既存の記事を編集するためには FORM の value値にログファイルのデータを読み込みます。
編集画面にリンクする為のフォームのほうを

<form action="./index.php?page=20&no=2" method="POST">
no. <input size="4" name="edno"> pass <input type="password" size="10" name="pass"> <input type="submit" name="delete" value="管理者削除"> <input type="submit" name="edit" value="管理者編集">
</form>

no.  pass    パスワードは password です

↑上はイメージ(動作しません)。
上記のようにしたうえで $_POST["edit"] が送られてきた場合、フォームの value値にログファイルから読み込んだ対象行のデータを表示させます。

if (isset($_POST["edit"])) { //修正フォーム表示
$edno = $_POST["edno"]; //POSTで渡された編集記事番号を $edno に代入
$pass = $_POST["pass"]; //POSTの値を受け取って変数に割り当てる
if ($pass == "password") { //パスワードが正しければ
$ediline = file("./bbslog.cgi"); //データを開いて
for ($i = 0; $i < count($ediline); $i++) { //展開する
$edit = explode("<>", $ediline[$i]); //区切り文字 <> で区切る
if ($edit[0] == $edno) { //編集対象行を探す
print "<div align='center'>¥n"; //以下、編集対象行をフォーム内に表示
print "<center>¥n";
print "No." . $edit[0] . " " . $edit[3] . " さんの書き込みを修正できます。<br>¥n<br>¥n";
print "<form action='./bbs.php' method='POST'>¥n";
print "<table cellspacing='4' cellpadding='0' width='600' border='0'>¥n";
print "<tr>¥n<td>¥n";
print "<font style='font-size:14px;color:#808080;'>name</font><br>¥n";
print "<input size='30' name='name' value='" . $edit[2] . "'><br>¥n";
print "<font style='font-size:14px;color:#808080;'>email</font><br>¥n";
print "<input size='30' name='email' value='" . $edit[3] . "'><br>¥n";
print "<font style='font-size:14px;color:#808080;'>url</font><br>¥n";
print "<input size='30' name='url' value='" . $edit[4] . "'><br>¥n";
print "<font style='font-size:14px;color:#808080;'>title</font><br>¥n";
print "<input size='30' name='title' value='" . $edit[5] . "'><br>¥n";
print "<font style='font-size:14px;color:#808080;'>comment</font><br>¥n";
$edcomment = str_replace("<br>", "¥n", $edit[6]); //<br>を¥nに変換
print "<textarea name='comment' rows='7' cols='68'>" . $edcomment . "</textarea><br>¥n";
print "<input style='cursor:hand;' type='submit' value='修正' name='editaction'>¥n<input type='hidden' name='editno' value='" . $edno . "'>¥n<input type='hidden' name='reno' value='" . $edit[1] . "'>¥n";
print "</td>¥n</tr>¥n";
print "</table>¥n";
print "</form>¥n";
print "</center>¥n";
print "</div>¥n";
}
}
}
}

comment は改行を含みますので <br> を改行記号(¥n)に置き換えてからテキストエリア内に表示させます。
さらにこのフォームから送られてきたデータ処理は、ログファイルを走査して編集対象行を探し、array_splice 関数で行を置き換えします。

if (isset($_POST["editaction"])) { //編集の場合
$editno = $_POST["editno"]; //POSTの値を受け取って変数に割り当てる
$reno = $_POST["reno"]; //POSTの値を受け取って変数に割り当てる
$edit = file("./bbslog.cgi"); //データを開いて
for ($i = 0; $i < count($edit); $i++) { //展開する
$ediline = explode("<>", $edit[$i]);
if ($ediline[0] == $editno) { //置き換え対象行を探す
$ediwrite = "$editno<>$reno<>$name<>$email<>$url<>$title<>$comment<>$time<>$ip<>¥n"; //置き換えする1行
array_splice($edit,$i,1,"$ediwrite"); //1行置き換え
}
}

実行
3. 全体の流れ

前回に引き続き全体の流れです。前回から追加になっている部分を赤文字にしました。

if (削除記事ナンバーが送られてきた場合) {
記事(スレッド)削除
}(管理者削除処理終わり)

if (レスフォームナンバーが送られてきた場合) {
レスフォーム表示
}(レスフォームナンバーが送られてきた場合終わり)
elseif (編集記事ナンバーが送られてきた場合) {
編集フォーム表示
}(編集フォームナンバーが送られてきた場合終わり)
else {(レスフォームナンバー・編集記事ナンバーが送られてきた場合以外)
   //新規投稿・レス投稿共通処理
   if (POSTに name か comment があれば) {
   受け取り処理をする、ログを走査して新投稿の記事番号を決める
          if (URLが書かれていた場合は) {//処理を飛ばす
             if (多重投稿の場合は) {//処理を飛ばす
   //共通処理ここまで
      if (返信投稿の場合) {
      処理をする
      }
      elseif (管理者編集の場合) {
      処理をする
      }
      else {//新規投稿の場合
      処理をする
      }
   }//投稿受け取り処理終わり
             }//多重投稿の場合はここまで飛ばす
          }//URLが書かれていた場合はここまで飛ばす
//最初の表示・新規投稿処理後の表示・レス投稿処理後の表示・記事削除後の表示・記事編集後の表示
}//レスフォームナンバー・編集記事ナンバーが送られてきた場合以外終わり)


うまくスクリプトが書けない方、すぐには環境(エディタなど)が整わない方、とにかく設置して動作を見たい方のために こちら からzip形式をダウンロードできるようにしました。


Fatal error: Uncaught Error: Undefined constant "Y.n.j" in /home/users/2/secret.jp-final/web/phpholiday/20/index.cgi:175 Stack trace: #0 /home/users/2/secret.jp-final/web/phpholiday/index.php(334): include() #1 {main} thrown in /home/users/2/secret.jp-final/web/phpholiday/20/index.cgi on line 175