Perl でページネーション (ページ送り) を作ってみたのでそのメモ。
DB に格納した大量のデータを一覧表示する際になくてはならないページネーションですが、これを自前で用意してみたらわりと面倒だったので書いておこうと思います。
まず、ページネーションを作る上で必要な情報はコレ。
- 対象データの全レコード数
- 全ページ数の算出
- 現在のデータ位置
- ページネーションを表示
DB はこんな具合になってます。
mysql> show columns from my_table; +---------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+----------------+ | id | int(16) | NO | PRI | NULL | auto_increment | | data1 | varchar(255) | NO | | NULL | | | data2 | varchar(255) | NO | | NULL | | | data3 | varchar(255) | NO | | NULL | | +---------+--------------+------+-----+---------+----------------+
対象データの全レコード数を取得する色々
まずは、全体の件数の取得から。
保存されているデータが全て表示対象の場合はこれで件数を取得する。
SELECT COUNT(id) FROM my_table;
保存されているデータのうち、data1 が hoge のものをカウントするにはこんな感じに。
SELECT COUNT(id) FROM my_table WHERE data1='hoge';
保存されているデータのうち、data1 が hoge かつ、data2, data3 に huga が含まれるものをカウントするにはこんな感じに。
SELECT COUNT(id) FROM my_table WHERE data1='hoge' AND (data2 LIKE '%huga%' OR data3 LIKE '%huga%');
全ページ数の算出
次は上記のデータより全ページ数を計算。1ページに30件まで表示する場合はこうなる。
my $view = 30; my $count = .... カウント処理 ....; my $total = int($count / $view);
int の部分が怪しいけどぱっと見は問題ないみたい。
現在のデータ位置
現在のデータ位置は URL のパラメータから取得する。
use CGI; my $page = $q->param('page') || 0; my $view = 30; my $cur = $page * $view; if ($page != 0) { $cur++; }
0ページ (1ページ目) 以外で現在位置を +1 しているのは SQL の LIMIT でデータを取得する必要があるから。
多分こうなるはず。
- 1ページ目: 0 ? 29 件目のレコード
- 2ページ目: 30 ? 59 件目のレコード
- 3ページ目: 60 ? 89 件目のレコード
表示データを取得する SQL はこんな具合に取ってくる。
SELECT COUNT(id) FROM my_table WHERE data1='hoge' AND (data2 LIKE '%huga%' OR data3 LIKE '%huga%') LIMIT $cur, $view;
ページネーションを表示
必要なデータは揃ったので後はページネーションを表示するだけ。
ループを使ってこんな感じに。
print "<ul class='pagination'>\n"; for (my $i = 0; $i <= $total; $i++) { my $p = $i + 1; if ($page == $i) { print "<li class='current'>"; } else { print "<li>"; } print "<a href='my.cgi?page=$i'>$p</a></li>\n"; } print "</ul>\n";
現在位置にもアンカーを付けてますがこんな感じで上手くいくと思う。
以上、ページネーションのメモでした。