filemakerを通じて、データベースというものの奥深さに今更ながら気付いてしまったボク。

基礎からのMySQL」を片手に、日々勉強中です。

さて、今日はまた一つ賢くなったのでメモっておこう。

<表示するレコードの範囲を決める>

例えば、100件のレコードを表示するとなった時、バカ正直に100件を縦に並べたらエラいことになる。

ウェブページというものがたとえ縦方向に無限だとしても、モノには限度というものがある。

従って、通常は10件ずつ程度に区切って表示しておき、“次の10件”や“前の10件”のように、ハイパーリンクで表示を切り替えるようにする。

このサイトでいえば、ちょうど“ボウリングの紆余曲折”の“スコア閲覧”ページがそれだ。

こんな時に便利なのが、コレ↓

$sql = "SELECT COUNT(*) FROM 'table'";
$res = mysql_query($sql);
list($total) = mysql_fetch_row($res);

$offset = $length * ($page - 1);

$sql = "SELECT `score` FROM 'table' ORDER BY `datetime` DESC LIMIT {$length} OFFSET {$offset}";
$res = mysql_query($sql);
while($row = mysql_fetch_array($res)){
  ・
  ・
  $contents .= ~~;
}

$limit = $length * $page;
$start = $offset + 1;
$end = ($total > $limit) ? $limit : $total;
$comment = ($start == $end) ? "{$start}" : "{$start}~{$end}";
echo "<p>{$comment}件目(全{$total}件中)を表示</p>";

$back = $page - 1;
$next = $page + 1;
echo "<p>";
if($page > 1) echo "<a href=\"index.php?page={$back}\">←前の{$length}件</a>";
if($page > 1 && $total > $limit) echo " / ";
if($total > $limit){
  $diff = $total - $end;
  $nextLength = ($diff >= $length) ? $length : $diff;
  echo "<a href=\"{$thisfile}?page={$next}\">→次の{$nextLength}件</a>";
}
echo "</p>";

echo $contents;

大体こんな感じっすかねえ。

まず大事なのは、7行目のMySQLクエリ文の、

LIMIT {$length} OFFSET {$offset}

のトコロ。

“LIMIT”で表示するレコード数を指定し、“OFFSET”で表示開始レコードのシフト数を指定する。

つまり、21~30行目を表示したければ、

LIMIT 10 OFFSET 20

とすれば良い。

あとはSQLの実行結果を連想配列として取得し、whileで廻しながらデータの整形をする。

で、15行目以降は“21~30件目(全100件中)を表示”みたいなモノを出力するためのもの。

“91~96件目(全96件中)を表示”のように、最後はちゃんと全件(この場合だと96件)分で終わるように工夫してある。

最後は“←前の10件”および“→次の10件”のハイパーリンク部分。

これも、1ページ目は“→次の10件”のみを表示、最後から2番目のページは“→次の6件”となるようにし、最後のページは“←前の10件”のみを表示するようにしている。

15行目以降に関しては前から書いていたコードだが、“LIMIT”と“OFFSET”を知らなかったせいで以前はwhileで廻す部分がかなり悲惨な事になっていた。

毎回毎回全件取り出しては、phpのwhile文の部分で表示すべきレコードをif文多用で制御していたもんだから、コードはややこしいしサーバーにも負担をかけていたんだろうなあ、、、

いやあ、賢くなるって、素晴しいね。