phpな休日 BBS sitemap
1. 返信投稿をログに挿入する

返信投稿があった場合は、ログファイルの途中に1行挿入する形になります。あるいは最下行を追加するケースもあります。最下行の場合は

array_push(今までのデータ, 追加する行のデータ);

と書きます。途中に挿入する場合は

array_splice(今までのデータ, 挿入場所, 0, 挿入する行のデータ);

と書きます。

また、私とsakuraさんのログを例に出しますと

5<>5<>haku<>email<>http://www.p-ho.net/<>title3<>comment3<>time<>iphost<>
6<>5<>sakura<>email<><>Re:title3<>response3<>time<>iphost<>
3<>3<>haku<>email<>http://www.p-ho.net/<>title2<>comment2<>time<>iphost<>
4<>3<>sakura<>email<><>Re:title2<>response2<>time<>iphost<>
1<>1<>haku<>email<>http://www.p-ho.net/<>title1<>comment1<>time<>iphost<>
2<>1<>sakura<>email<><>Re:title1<>response1<>time<>iphost<>

[項目1] の数字が書き込まれた順番です。この状態で上から3行目の親記事に返信する場合、すでに返信がひとつついていますので [記事番号4] の下に [記事番号7] として書き込まれるようにします。
【[記事番号1] の上に [記事番号7] として書き込まれるようにします。】というほうが処理のイメージです。

5<>5<>haku<>email<>http://www.p-ho.net/<>title3<>comment3<>time<>iphost<>
6<>5<>sakura<>email<><>Re:title3<>response3<>time<>iphost<>
3<>3<>haku<>email<>http://www.p-ho.net/<>title2<>comment2<>time<>iphost<>
4<>3<>sakura<>email<><>Re:title2<>response2<>time<>iphost<>
7<>3<>haku<>email<>http://www.p-ho.net/<>Re:title2<>comment2<>time<>iphost<>
1<>1<>haku<>email<>http://www.p-ho.net/<>title1<>comment1<>time<>iphost<>
2<>1<>sakura<>email<><>Re:title1<>response1<>time<>iphost<>

上記の赤文字行を追加するために、まず返信用フォームからPOSTで受け取った bbsresno(3) を探します。3 が見つかったら、見つかったという印($insert = 1)をつけて今度は [項目2] を走査しながら、3 でなくなる行(次のスレッド)を探します。見つかったらそこに新たな行を挿入します。
次のスレッドが見つからなかった場合は、そのスレッドが最終スレッドであるということなので、ログの最後に行を追加します。

$insert = 0; //$bbsresno と $list[0] が同一の行(親記事)を探す
for ($i = 0; $i < count($data); $i++) { //走査する
$list = explode("<>", $data[$i]); //区切り文字 <> で区切る
if ($insert == 0) { //まだ親記事が見つかっていない
if ($bbsresno == $list[0]) { //ここが親記事
$insert = 1; //親記事を見つけた印
}
}
else { //レス記事は飛ばして
if ($bbsresno != $list[1]) { //次の親記事まできたら
array_splice($data, $i, 0, $reswrite); //新しい行をここに挿入
$insert = 0; //挿入が済んだ印
break;
}
}
}
if ($insert == 1) {array_push($data, $reswrite);} //挿入が済んでいない(次の親記事がない=最下行であるということ)の場合

実行
2. 返信投稿があったスレッドをログの先頭に上げる

返信投稿があったスレッドをログの一番上に移動します。

ログを走査していって、目的のスレッドを見つけたらカウントを始めます。目的のスレッドが何行目から始まって、何行になるかを確認したら
array_splice($data, 上からの行数, スレッドの行数)
でスレッドごと削除。削除した内容を $string 変数に代入しておいて
array_merge($string, $data)
と先頭に追加する形で移動します。

$linecount = 0; //行数カウント
for ($i = 0; $i < count($data); $i++) { //走査する
$list = explode("<>", $data[$i]); //区切り文字 <> で区切る
if ($bbsresno == $list[0]) { //$bbsresnoを頼りに親記事を探す
$top = $i; //上からの行数
$linecount++; //行数をプラス
}
elseif ($bbsresno == $list[1]) {
$linecount++; //行数をプラス
}
}
if (isset($linecount)) {
$string = array_splice($data, $top, $linecount); //移動する行を削除
$newdata = array_merge($string, $data); //先頭に足す
}

処理が完了したらデータを保存します。

$redata = fopen("./bbslog.cgi", "w"); //書き込みモードでファイルを開
flock($redata, LOCK_EX); //ファイルロック
foreach($newdata as $value) { //配列処理して
fputs($redata, $value);} //書き込む
flock($redata, LOCK_UN); //ファイルロック解除
fclose($redata); //ファイルを閉じる

実行
3. BBS 全体の流れ

ここまでの全体の流れをざっと明記しておきます。

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


Fatal error: Uncaught Error: Undefined constant "Y.n.j" in /home/users/2/secret.jp-final/web/phpholiday/19/index.cgi:146 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/19/index.cgi on line 146