1頁の記事表示数を指定!

 ここまでの掲示板では、書き込み記事50件を一気に表示するだけでした。これでは表示全体が縦に伸びるばかりで、全体として少々見づらくなってしまいます。そこで、今回はよく見かける1ページ毎の記事表示を切り替える機能をご紹介しましょう。

変更部分

 まず1ページの記事表示数を10件に決め、変数$pageviewに格納します。ついでに記事の最大記憶数$maxも100に増やしてやりましょう。次に書き込み記事表示欄の最下部に次ページへ飛ぶ為のボタンを表示させてやらねばなりません。これはフォームタグで作成します。また同時に、書き込み記事を一覧表示する処理「foreach関数」の部分に、表示件数を指定の10件毎に分割表示する処理も施してやらねばなりません。

 ここの処理内容は理屈的にちょっとややこしいので、よーくコードをご覧になって下さい。ソースを示した後で実際の具体的な処理の流れもご説明しますが、各変数に格納された数値の流れを追って行けば理解が早いかと思います。

実際のソース

 では実際のソースを見てみましょう。該当の変更箇所は色を変えて示しています。よく注意してご覧になって下さい。

#!/usr/bin/perl
# ↑あなたが加入しているプロバイダの「perl」言語が使用できるパスを指定します。
# 一般的には「#!/usr/local/bin/perl」か「#!/user/bin/perl」で大丈夫。
require '../jcode.pl';
$bbs_title = '簡単掲示板プラス';
$datafile = 'keijiban4.txt';
$cgi_name = 'keijiban4.cgi'; #ここで使うCGIスクリプトの名前
$max = 100; #記事の最大記憶数
$pageview = 10; #1ページの記事表示数
$passwd = '****'; #管理者用パスワード
#==============初期設定が必要なのはここまでです=================================
($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year += 1900;
$mon = sprintf("%02d", $mon + 1);
$day = sprintf("%02d", $day);
$hour = sprintf("%02d", $hour);
$min = sprintf("%02d", $min);
$date_now = "$year年$mon月$day日 $hour時$min分";
$softagent = $ENV{'HTTP_USER_AGENT'}; #訪問者のブラウザを取得
$hostaddr = &domain_name; #訪問者のホスト名を取得
if ($ENV{'REQUEST_METHOD'} eq "POST") {
read(STDIN, $QUERY_DATA, $ENV{'CONTENT_LENGTH'});
} else { $QUERY_DATA = $ENV{'QUERY_STRING'}; }
@pairs = split(/&/,$QUERY_DATA);
foreach $pair (@pairs) {
 ($name, $value) = split(/=/, $pair);
 $value =~ tr/+/ /;
 $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
 $value =~ s/</&lt;/g;
 $value =~ s/>/&gt;/g;
 $value =~ s/\n//g;
 $value =~ s/\,//g;
 &jcode'convert(*value,'sjis');
 $FORM{$name} = $value;
}
if (!open(NOTE,"$datafile")) { &error(bad_file); }
@DATA = <NOTE>;
close(NOTE);
if ($FORM{'action'} eq 'delete') {
 if ($FORM{'password'} eq '') { &error(not_pass); }
 if ($FORM{'code'} < 1) { &error(bad_code); }
 $i = 0; $match = 0;
 foreach $line (@DATA) {
  ($date,$code,$name,$email,$HP,$subject,$comment,$pass,$host,$agent) = split(/\,/,$line);
  if ($FORM{'code'} == $code) {
   if ($FORM{'password'} eq $pass || $FORM{'password'} eq $passwd) {
    splice(@DATA,$i,1);
    $match = 1; last;
   }
  }
  $i++;
 }
 if ($match) {
  if (!open(NOTE,">$datafile")) { &error(bad_file); }
  print NOTE @DATA;
  close(NOTE);
 }
} elsif ($FORM{'action'} eq 'regist') {
 if ($FORM{'name'} eq '') { &error(bad_name); }
 if ($FORM{'comment'} eq '') { &error(bad_comment); }
 $count = @DATA;
 if ($count > $max) { pop (@DATA); }
 if ($count < 1) {
  $new_code = 1;
 } else {
  ($date,$code,$name,$email,$HP,$subject,$comment,$pass,$host,$agent) = split(/\,/,$DATA[0]);
  $new_code = $code + 1;
 }
 $value = "$date_now\,$new_code,$FORM{'name'}\,$FORM{'email'}\,$FORM{'HP'}\,$FORM{'subject'}\,$FORM{'comment'}\,$FORM{'pass'}\,$hostaddr,$softagent\n";
 unshift(@DATA,$value);
 if (!open(NOTE,">$datafile")) { &error(bad_file); }
 print NOTE @DATA;
 close(NOTE);
}
print "Content-type: text/html\n\n";
print "<html><head>\n";
print "<title>" . $bbs_title . "</title></head>\n";
print "<body bgcolor=#FFFFDD text=#000000 link=#FF0000 vlink=#FF0000>\n";
print "<form action=$cgi_name method=POST>\n";
print "<input type=hidden name=action value=regist>\n";
print "<center><font size=6>" . $bbs_title . "</font></center>\n";
print "<center><font color='red'>お名前とコメントは、必ずご記入下さい。尚、記事の最大記録数は50件です。</font></center>\n";
print "<table border=0 cellspacing=1>\n";
print "<tr><td align=right>お名前</td>\n";
print "<td><input type=text size=29 name=name></td></tr>\n";
print "<tr><td align=right>E-mail</td>\n";
print "<td><input type=text size=29 name=email></td></tr>\n";
print "<tr><td align=right>HomePage</td>\n";
print "<td><input type=text size=50 name=HP></td></tr>\n";
print "<tr><td align=right>題名</td>\n";
print "<td><input type=text size=50 name=subject></td></tr>\n";
print "<tr><td align=right>コメント</td>\n";
print "<td><textarea name=comment rows=4 cols=60></textarea></td></tr>\n";
print "<tr><td align=right>削除キー</td>\n";
print "<td><input type=password size=10 name=pass>\n";
print "<font size=-1 color='red'> *英数8文字以上推奨</font></td></tr>\n";
print "<tr><td></td><td><input type=submit value=書き込み>";
print " <input type=reset value=取り消し></td></tr>\n";
print "</table></form>\n";
if ($FORM{'pline'} eq '') { $pline = 0; } else { $pline = $FORM{'pline'}; }
$end_data = @DATA - 1;
$page_end = $pline + ($pageview - 1);
if ($page_end >= $end_data) { $page_end = $end_data; }

print "<form action=$cgi_name method=POST>\n";
print "<input type=hidden name=action value=delete>\n";
foreach ($pline .. $page_end) {
 ($date,$code,$name,$email,$HP,$subject,$comment,$pass,$host,$agent) = split(/\,/,$DATA[$_]);
*「$FORM{'pline'} eq ''」は、書き込み記事表示欄の最下部にある「次のページへ」のボタンが押されていない事を意味します。「$pline = 0」と初期値が0に指定されているのは、プログラムの上ではもう常識ですね(^。^)つまり、最初の1ページ目は、0〜9番目の記事(10件)が表示されると言う訳です。

*変数$end_dataと$page_endは、書き込み記事を1ページ毎に分割して表示する為に使われています。ここに格納されていく数値が曲者なんです。

*最後の「$DATA[$_]」の「$_」は特殊変数で、この処理時のデフォルトの値を表しています。
 $comment =~ s/\r/<br>/g;
 print "<hr>\n";
 print "<input type=radio name=code value=$code>\n";
 print "<font color='blue' size=4><b>$subject</b></font>\n";
 if ($email ne "") {
  print "<a href=mailto:$email><strong> $name</strong></a>\n";
 } else { print "<strong> $name</strong>\n"; }
 if ($HP ne "") {
  print "<a href=$HP target=_top> HomePage</a>\n";
 }
 print "<font size=-1> $date</font>\n";
 print "<blockquote>$comment</blockquote>\n";
 print "<font size=-1>[$host] $agent</font>\n";
}
print "<hr>\n";
print "削除用パスワード:<input type=password size=10 name=password>";
print "<input type=submit value=削除>\n";
print "</form>\n";
$next_line = $page_end + 1;
if ($page_end != $end_data) {
 print "<form method=POST action=$cgi_name>\n";
 print "<input type=hidden name=pline value=$next_line>\n";
 print "<input type=submit value=次のページへ>\n";
 print "</form>\n";
}

print "</body></html>\n";
exit;
*書き込み記事の表示欄の最下部に、次のページに飛ぶ為のボタンを表示します。ここでは、変数$plineのvalueがどんな値になるか注意しなければいけません。
#====================訪問者のホスト名を取得するサブルーチン======================
sub domain_name {
 local($addr) = $ENV{'REMOTE_ADDR'};
 local($_) = gethostbyaddr(pack("C4",split(/\./,$addr)),2);
 if ($_ eq '') { $_ = $addr; }
 $_;
}
#================================エラー処理ルーチン=============================
sub error {
$error = $_[0];
if ($error eq "bad_file") { $msg = 'ファイルのオープン、入出力に失敗しました。'; }
elsif ($error eq "bad_name") { $msg = 'お名前が記入されていません。'; }
elsif ($error eq "bad_comment") { $msg = 'コメントが記入されていません。'; }
elsif ($error eq "not_pass") { $msg = 'パスワードが記入されていません。'; }
elsif ($error eq "bad_code") { $msg = '削除記事番号が不正です。'; }
else { $msg = '原因不明のエラーで処理を継続できません。'; }
print "Content-type: text/html\n\n";
print "<html><head><title>" . $bbs_title . "</title></head>\n";
print "<body bgcolor=#FFFFDD text=#000000 link=#FF0000 vlink=#FF0000>\n";
print "<center><h2>エラーです!</h2>\n";
print "やり直して下さい。<hr>\n";
print "<b>" . $msg . "</b></center>\n";
print "</body></html>\n";
exit;
}

実際の処理の流れ

 ここでは処理の該当部分だけを抜き出して、その実際の処理の流れを詳しく見てみましょう。処理の該当部分は次の2箇所です。

前半部分

1. if ($FORM{'pline'} eq '') { $pline = 0; } else { $pline = $FORM{'pline'}; }
2. $end_data = @DATA - 1;
3. $page_end = $pline + ($pageview - 1);
4. if ($page_end >= $end_data) { $page_end = $end_data; }
5. foreach ($pline .. $page_end) {

後半部分

6. $next_line = $page_end + 1;
7. if ($page_end != $end_data) {
print "<form method=POST action=$cgi_name>\n";
print "<input type=hidden name=pline value=$next_line>\n";

(1)記事数が10件までは、「次のページへ」のボタンは表示されない

 10件目の記事を投稿した場合の処理の流れを見て行きましょう。

1.「次のページへ」ボタンは押されていないので、「$pline = 0」となる。
2.@DATAの値は10だから、「$end_data = 9」となる。
3.$pageviewの値は10だから、「$page_end = 9」となる。
4.条件式「$page_end >= $end_data」が成り立つので、「$page_end = 9」となる。
5.foreach関数の処理範囲は(0 .. 9)となる。
6.「$next_line = 10」となる。
7.条件式「$page_end != $end_data」は成り立たないので、次のボタン表示処理は行われない。

(2)「次のページへ」のボタンが初めて表示される時

 まず最初にこのボタンが表示されるのは、11件目の記事を投稿した時です。では、この時の処理の流れを見て行きましょう。

1.「次のページへ」ボタンは押されていないので、「$pline = 0」となる。
2.@DATAの値は11だから、「$end_data = 10」となる。
3.$pageviewの値は10だから、「$page_end = 9」となる。
4.条件式「$page_end >= $end_data」は成り立たないので、そのまま「$page_end = 9」となる。
5.foreach関数の処理範囲は(0 .. 9)となる。1ページ目を表示。
6.「$next_line = 10」となる。
7.条件式「$page_end != $end_data」が成り立つので、次のボタン表示処理が行われ、変数$plineの値は10となる。

(3)ここで「次のページへ」のボタンを押した場合

 ここで初めて表示された「次のページへ」のボタンを押した場合の処理の流れを見てみましょう。

1.「次のページへ」ボタンが押されたので、「$pline = 10」となる。
2.@DATAの値は11だから、「$end_data = 10」となる。
3.$pageviewの値は10だから、「$page_end = 19」となる。
4.条件式「$page_end >= $end_data」が成り立つので、「$page_end =10」となる。
5.foreach関数の処理範囲は(10 .. 10)となる。2ページ目の記事1件だけを表示。
6.「$next_line = 20」となる。
7.条件式「$page_end != $end_data」は成り立たないので、次のボタン表示処理は行われない。

 このように、変数$plineの値は0、10、20と増えて行くようになります。これは各ページの表示記事番号がそれぞれ「0〜9」「10〜19」「20〜29」となるからです。

訪問者の情報をゲット! 前へ

HOME

次へ 標準掲示板