多機能掲示板Upgrade
予てからご希望のあった、レスが付いた時にその表示場所をトップに移動させる機能ですが、ようやくちょっと時間が出来たので、既存のスクリプトを改造する事が出来ました。とは言っても、記事書き込みの際の処理に、この部分を追加しただけなんですけどね(^^ゞ
スクリプトの内容は、ここの第17章の「多機能掲示板(修正版)」をベースにしていますので、以下に今回の変更部分のみ解説を加えたいと思います。
追伸・・・後日、他にも細かな修正を加えました。書き込み時のエラー表示とか、ページ移動のボタン追加とか。書き込み記事表示の際のグループ分けも、従来の水平線使用からテーブル表示に変更!
*注意…このスクリプトはPHP4.2.0以降のスーパーグローバル変数に対応したものになっていません。ご注意下さい。
<?php //===================初期設定===================== //時間の取得 $now = date("Y/m/d H:i:s"); $data_file = "./g_book7.dat"; //データファイル名 $data_max = 100; //データ最大記録数 $page_view = 10; //1ページの記事表示件数 $homegif = "./home.gif"; //ホームページへのリンク用画像 $passwd = "777"; //管理者用パスワード ?> |
初期設定をファイルの先頭に移動しました。 データ保存用ファイルの名前も「g_book7.dat」に変更。 |
<HTML> <HEAD> <TITLE>多機能掲示板Upgrade</TITLE> <STYLE TYPE="text/css"> <!-- :link { Color : blue ; Text-Decoration : None } :active { Color : blue ; Text-Decoration : None } :visited { Color : blue ; Text-Decoration : None } A:hover { Color : blue ; Text-Decoration : Underline } --> </STYLE> </HEAD> <BODY BGCOLOR="#ffffee"> <FORM ACTION="<?php echo $PHP_SELF; ?>" METHOD="POST" NAME="line"> <P><INPUT TYPE="HIDDEN" NAME="action" SIZE="-1" VALUE="regist"></P> <P ALIGN="CENTER"><FONT SIZE="6" COLOR="#000099">多機能掲示板Upgrade</FONT></P> <P ALIGN="CENTER"><FONT SIZE="2" COLOR="red">お名前とコメントは必ず書き込んで下さい。エラーになります。記事の最大記録数は<?php echo $data_max; ?>件です。</FONT></P> <BLOCKQUOTE> <P> <TABLE BORDER="0" WIDTH="88%"> <TR> <TD WIDTH="12%" ALIGN="RIGHT"> <P ALIGN="RIGHT">お名前 </TD> <TD WIDTH="88%"><INPUT TYPE="TEXT" NAME="name" SIZE="15"></TD> </TR> <TR> <TD WIDTH="12%" ALIGN="RIGHT"> <P ALIGN="RIGHT">E-mail </TD> <TD WIDTH="88%"><INPUT TYPE="TEXT" NAME="email" SIZE="25"></TD> </TR> <TR> <TD WIDTH="12%" ALIGN="RIGHT"> <P ALIGN="RIGHT">HomePage </TD> <TD WIDTH="88%"><INPUT TYPE="TEXT" NAME="hp" SIZE="40"></TD> </TR> <TR> <TD WIDTH="12%" ALIGN="RIGHT"> <P ALIGN="RIGHT">題目 </TD> <TD WIDTH="88%"><INPUT TYPE="TEXT" NAME="subject" SIZE="40"></TD> </TR> <TR> <TD WIDTH="12%" ALIGN="RIGHT"> <P ALIGN="RIGHT">題目色 </TD> <TD WIDTH="88%"> <INPUT TYPE="RADIO" NAME="scolor" VALUE="blue" checked><B><FONT COLOR="blue">青</FONT></B> <INPUT TYPE="RADIO" NAME="scolor" VALUE="red"><B><FONT COLOR="red">赤</FONT></B> <INPUT TYPE="RADIO" NAME="scolor" VALUE="green"><B><FONT COLOR="green">緑</FONT></B> <INPUT TYPE="RADIO" NAME="scolor" VALUE="#996600"><B><FONT COLOR="#996600">茶</FONT></B> <INPUT TYPE="RADIO" NAME="scolor" VALUE="#660099"><B><FONT COLOR="#660099">紫</FONT></B> </TD> </TR> <TR> <TD WIDTH="12%" ALIGN="RIGHT"> <P ALIGN="RIGHT">コメント </TD> <TD WIDTH="88%"><TEXTAREA NAME="comment" ROWS="4" COLS="60"></TEXTAREA></TD> </TR> <TR> <TD WIDTH="12%"> <P ALIGN="RIGHT">削除キー </TD> <TD WIDTH="88%"><INPUT TYPE="PASSWORD" NAME="pass" SIZE="7"><FONT SIZE="2" COLOR="#CC0000"> *半角英数4文字以上推奨。削除キーを設定すると、いつでもご自分の記事を削除できます。</FONT></TD> </TR> <TR> <TD WIDTH="12%"> </TD> <TD WIDTH="88%"> <?php if ($flags == 'return') { print "<input type=submit value=[" . $return . "]に返信>\n"; print "<input type=hidden name=ress value=$code>\n"; } else { print "<INPUT TYPE=SUBMIT VALUE=書き込み> <INPUT TYPE=RESET VALUE=リセット>\n"; } ?> </TD> </TR> </TABLE> </FORM> |
題名を変更! 修正版スクリプトのファイル名は、「g_book7.php」となります。 記事の最大記録数の表示は、初期設定から呼び出すようにしました。 又、リンク表示等の文字色の設定を追加しました。 |
<?php //===============データの削除================== if ($action == "delete") { if(($delcode != "") && ($password != "")){ $delfile = file($data_file); $fp = fopen($data_file, "w"); for($i=0; $i<sizeof($delfile); $i++){ list($dcode,$dress,$dname,$demail,$dhp,$dsubject,$dscolor,$dcomment,$dpass,$dnow,$dhost,$dagent) = split( ",", $delfile[$i]); if (($password == $dpass) || ($password == $passwd)) { if ($delcode != $dcode) { fputs($fp,$delfile[$i]); } } else { fputs($fp,$delfile[$i]); } } fclose($fp); } } //===============インライン関数=================== function inline_link($link){ $link = ereg_replace("(https?|ftp|news)(://[[:alnum:]\+\$\;\?\.%,!#~*/:@&=_-]+)","<a href=\"\\1\\2\" target=\"_blank\">\\1\\2</a>",$link); return $link; } |
従来と同じ。 |
//===============データの書き込み================= if ($action == "regist") { if (($name != "") && ($comment != "")) { $code = time(); //アクセス時の秒数 //ホスト名を取得 $host = getenv("REMOTE_HOST"); $addr = getenv("REMOTE_ADDR"); if($host == "" || $host ==$addr){ $host = gethostbyaddr($addr); } //訪問者のブラウザ名を取得 $agent = getenv("HTTP_USER_AGENT"); //ここから書き込みデータの調整 $name = htmlspecialchars($name); //特殊文字のHTMLエントリへの変換 $email = htmlspecialchars($email); $hp = htmlspecialchars($hp); $subject = htmlspecialchars($subject); $comment = htmlspecialchars($comment); $comment = nl2br($comment); //HTML改行文字の挿入 $comment = str_replace("\r", "", $comment); //文字列の置換 $comment = str_replace("\n", "", $comment); //ログファイルの区切文字(",")と区別するために文字コード(,)に書き換える。 $name = str_replace(",", ",",$name); $email = str_replace(",", "",$email); $hp = str_replace(",", "",$hp); $subject = str_replace(",", ",",$subject); $comment = str_replace(",", ",",$comment); //インラインリンクを実現(URLのみ) $comment = inline_link($comment); //配列要素を文字列により連結 $input_msg = implode(",", array($code,$ress,$name,$email,$hp,$subject,$scolor,$comment,$pass,$now,$host,$agent)); $message = file($data_file); $fp = fopen($data_file, "w"); rewind($fp); fputs($fp, "$input_msg\n"); //最大記録数の調整 if(($data_max * 1.2) < sizeof($message)) $msg_num = $data_max - 1; else $msg_num = sizeof($message); for($i = 0; $i < $msg_num; $i++){ fputs($fp, $message[$i]); } fclose($fp); unset($message); |
記事番号に、アクセス時の秒数を使うようにしました。それぞれに常に固有の記事番号を得るためです。 従来の通し番号だと、エラーが出てしまったもので…(^^ゞ 又、従来の不要な文字処理を削除しました。 尚、書き込み記事の最大記録数の調整部分ですが、初期設定値の1.2倍を超えた場合に処理を実行するよう変更しました。この方が効率がいいもので(^^ゞ 他は従来と同じです。 |
//返信があった時の親記事の移動 if($ress){ //親記事を配列に格納後、削除 $sfile = file($data_file); $fp = fopen($data_file, "w"); for($i=0; $i<sizeof($sfile); $i++){ list($scode,$sress,$sname,$semail,$shp,$ssubject,$sscolor,$scomment,$spass,$snow,$shost,$sagent) = split( ",", $sfile[$i]); if($ress == $scode){ $CHOICE = $sfile[$i]; $sfile[$i] = ""; } fputs($fp,$sfile[$i]); } fclose($fp); unset($sfile); //引き抜いた親記事をファイルの先頭に書き込み $message2 = file($data_file); $fp = fopen($data_file, "w"); rewind($fp); fputs($fp, "$CHOICE"); for($i = 0; $i < sizeof($message2); $i++){ fputs($fp, $message2[$i]); } fclose($fp); unset($message2); } |
■今回の追加部分 変数$ressに返信すべき親記事の記事番号が格納されていたら、以下の処理を行います。 まずログファイルを開いて、書き込み記事をfor文で一つずつチェックし、変数$ressの値と変数$scode(親記事の記事番号)の値が等しければ、その親記事の内容を変数$CHOICEに書き込んで、ログファイル中のその親記事を一旦削除します。 次に、再びログファイルを開き、先ほど抜き取った親記事の内容を格納した変数$CHOICEの値を、ログファイルの先頭に書き込み、元のログファイルの内容も追加挿入し、ログファイルを閉じます。 これで返信のあった親記事の場所が、ログファイルの先頭に移動し、記事の一覧表示も修正されます。 |
}else{ print "<B>※必須項目が書き込まれていません。やり直して下さい。</B><A HREF=JavaScript:history.back(); onMouseOver=this.style.color='red' onMouseOut=this.style.color='blue'>[一つ前のページへ]</A>\n"; exit; } |
書き込みの際に必須項目が抜けていた場合、エラー表示を行うようにしました。 |
} //親記事だけを抜き出す $message = file($data_file); for($i=0; $i<sizeof($message); $i++){ list($rcode,$rress,$rname,$remail,$rhp,$rsubject,$rscolor,$rcomment,$rpass,$rnow,$rhost,$ragent) = split( ",", $message[$i]); if($rress == ""){ $PARENT[] = $message[$i]; } } |
従来と同じ。 |
//==================HTML表示====================== //1ページ当たりの表示件数の調整 $msg_count = count($PARENT); if($pline == "") $p_line = 0; else $p_line = $pline; $end_data = $msg_count - 1; $page_end = $p_line + ($page_view - 1); if($page_end >= $end_data) $page_end = $end_data; for($i=$p_line; $i<=$page_end; $i++){ list($code2,$ress2,$name2,$email2,$hp2,$subject2,$scolor2,$comment2,$pass2,$now2,$host2,$agent2) = split(",", $PARENT[$i]); //親記事の表示 print "<table border=1 bordercolor='green' width=88%>\n"; print "<tr><td>\n"; print "<form method=POST action=$PHP_SELF>\n"; print "<input type=radio name=delcode value=$code2>\n"; print "<font size=4 color=$scolor2><b>$subject2</b></font>\n"; if($email2 != "") print " <a href=mailto:$email2><b>$name2</b></a>\n"; else print " <b>$name2</b>\n"; if($hp2 != ""){ print " <a href=$hp2 target=_top><img src=$homegif border=0></a>\n"; } print " <font size=2 color='green'>$now2</font>\n"; print "<input type=hidden name=action value=delete>\n"; print "<font size=2>パスワード:</font><input type=password size=7 name=password>\n"; print "<input type=submit value=削除>\n"; print "</form>\n"; print "<blockquote>$comment2<br><br>\n"; print "<form method=POST action=$PHP_SELF>\n"; print "<input type=submit value=返信>\n"; print "<input type=hidden name=code value=" . $code2 . ">\n"; print "<input type=hidden name=return value=" . $subject2 . ">\n"; print "<input type=hidden name=flags value=return>\n"; print "<font size=2>[$host2] $agent2</font>\n"; print "</form></blockquote>\n"; //返信記事の表示 for($j=0; $j<sizeof($message); $j++){ list($code3,$ress3,$name3,$email3,$hp3,$subject3,$scolor3,$comment3,$pass3,$now3,$host3,$agent3) = split(",", $message[$j]); if ($code2 == $ress3) { print "<blockquote>\n"; print "<form method=POST action=$PHP_SELF>\n"; print "<input type=radio name=delcode value=$code3>\n"; print "RE:<font color=$scolor3><b>$subject3</b></font>\n"; if ($email3 != "") { print " <a href=mailto:$email3><strong>$name3</strong></a>\n"; } else { print " <strong>$name3</strong>\n"; } if($hp3 != ""){ print " <a href=$hp3 target=_top><img src=$homegif border=0></a>\n"; } print " <font size=2 color='green'>$now3</font>\n"; print "<input type=hidden name=action value=delete>\n"; print "<font size=2>パスワード:</font><input type=password size=7 name=password>\n"; print "<input type=submit value=削除>\n"; print "<blockquote>$comment3<br><br>\n"; print "<font size=2>[$host3] $agent3</font></blockquote>\n"; print "</form></blockquote>\n"; } } print "</td></tr></table><br>\n"; } unset($message); ?> |
書き込み記事のグループ分けに従来は水平線を使用していましたが、変更ついでにテーブル表示に変えました。この方が見た目がスッキリすると思います。 他は従来と同じ。 |
<P> <TABLE BORDER="0" WIDTH="88%"> <TR> <TD WIDTH="50%"> <?php if($page_end >= $page_view){ $page_count = floor($page_end / $page_view); $prev_line = ($page_count - 1) * $page_view; print "<form method=Post action=$PHP_SELF>\n"; print "<input type=hidden name=pline value=$prev_line>\n"; print "<input type=submit value=前のページ>\n"; print "</form>\n"; }else{ print " \n"; } ?> </TD> <TD WIDTH="50%"><P ALIGN="RIGHT"> <?php $next_line = $page_end + 1; if($page_end != $end_data){ print "<form method=Post action=$PHP_SELF>\n"; print "<input type=hidden name=pline value=$next_line>\n"; print "<input type=submit value=次のページ>\n"; print "</form>\n"; }else{ print " \n"; } ?> </TD> </TR> </TABLE> |
「前のページ」ボタンも表示するよう変更しました。 表示位置の調整のため、テーブルの中に入れています。 ページ移動の為の値を求める際には、下のfloor関数を使っています。求め方は、コード内容から推察して下さい。 ★int floor ( float number )関数・・・引数 number の小数点以下を切り捨てた値を返します。 |
</BLOCKQUOTE> </BODY> </HTML> |
従来と同じ。 |
*上の内容をこのまま複写しても動きません。何故なら、表示を見やすくする為コード中に全角スペースが入っているからです。実際にお使いになる時は、この点を修正してからサーバにアップして下さい。