pagenationを実現するモジュールあれこれ
俺々ライブラリ・俺々フレームワーク生活からの脱却を目指すべく、今後即戦力になる武器を少しずつ模索していたりする。pagenationも自作のページャーを利用していたのだが、改めて探してみると似たようなモジュールが色々と見つかったので、それぞれの特徴を大雑把に比較してみた。なお、以下で $dumper は Dumpvalue.pm のインスタンス。
HTML::Pager
my $pager = HTML::Pager->new( query => CGI->new, get_data_callback => sub { my ($offset, $rows) = @_; return [ $model->get_data($offset, $rows) ]; }, rows => 100, page_size => 10 ); print $pager->output;
最古参のpagenationモジュール。提供されているのは「ページャーの付いたエントリ一覧のHTML」を作成する機能のみであり、一覧を作るために「エントリを抽出して返すcode-ref」を渡さなくてならない。他にもCGI.pmのインスタンスを渡す必要があったり、書き出されるHTMLがテーブルで構成されていたり、流石に現代で使うにはレガシー過ぎる印象。
HTML::Paginator
my $pager = HTML::Paginator->new($entries_per_page, @entries); @entries = $pager->Contents($now_page); print $pager->Page_Nav_HTML($now_page);
最終更新が2003年頃とかなり古いモジュール。エントリ全件が入ったリストを渡して、そこから指定ページの分を切り出して使うという発想に基づく。ページャーのHTMLを書き出す機能も備えるが、「前へ」「次へ」に相当するリンクが作られるのみ。敢えて使う理由が思い浮かばない。
Data::Pagination
my $pager = Data::Pagination->new($total_entries, $entries_per_page, $pages_per_set, $current_page);
コンストラクタ以外のメソッドを持たず、インスタンスが作成された時点でpagenationに必要な値を計算してプロパティにセットする。 $dumper->dumpValue($pager) すると、以下のように出力される($total_entries=30, $entries_per_page=5, $pages_per_set=1, $current_page=3 の場合)。
'current_page' => 3 'end_of_set' => 3 'end_of_slice' => 14 'entries_per_page' => 5 'length_of_slice' => 5 'next_page' => 4 'page_of_next_set' => 4 'page_of_prev_set' => 2 'pages_per_set' => 1 'prev_page' => 2 'start_of_set' => 3 'start_of_slice' => 10 'total_entries' => 30 'total_pages' => 6
Data::Scroller
my $page_params = Data::Scroller->new( max_value => $total_entries, selected => $selected, increment => $entries_per_page, )->display;
display()はpagenationに必要な値をhash-refの構造体に詰めて返す。 $dumper->dumpValue($page_params) すると、以下のように出力される($total_entries=30, $selected=2, $entries_per_page=10 の場合)
'page_first' => 0 'page_increment' => 10 'page_last' => 20 'page_list' => ARRAY(0x3dee6c) 0 HASH(0xb1a74c) 'page_display' => 1 'page_value' => 0 1 HASH(0xb7798c) 'page_display' => 2 'page_value' => 10 2 HASH(0xb779cc) 'page_display' => 3 'page_value' => 20 'page_name' => 'row_num' 'page_next' => 10 'page_prev' => 0 'page_total' => 3
CGI::Pager
my $pager = CGI::Pager->new( total_count => $total_entries, page_len => $entries_per_page, ); foreach my $page ($pager->pages) { if ($page->{is_current}) { print $page->{number}; } else { print "<a href=\"$page->{url}\">$page->{number}</a>"; } } print $pager->html('combined');
pagenationに必要な情報を返す一通りのメソッドを提供しており、またいくつかのパターンでページャーのHTMLを作成する機能も備える。エントリのoffsetは URI::QueryParam を利用していわゆるクエリ・パラメータから自動的に取得する。
上記の例にある最後のprint文は以下のHTMLを出力する($total_entries=30, $entries_per_page=5, offset=7の場合)
<a href="">First</a> <a href="?offset=2">Previous</a> <strong>1</strong> <a href="?offset=5">2</a> <a href="?offset=10">3</a> <a href="?offset=15">4</a> <a href="?offset=20">5</a> <a href="?offset=25">6</a> <a href="?offset=12">Next</a> <a href="?offset=25">Last</a>
Data::Page
my $page = Data::Page->new($total_entries, $entries_per_page, $current_page); print " First page: ", $page->first_page, "\n"; print " Last page: ", $page->last_page, "\n"; print "First entry on page: ", $page->first, "\n"; print " Last entry on page: ", $page->last, "\n";
シンプルなインターフェースでpaginationの最低限の機能だけを提供する定番モジュール。ページャーをHTMLに書き出す機能などはない。
Data::Pageset や Data::Page::Navigation など、 Data::Page を親クラスにしたバリエーション的なモジュールがいくつも存在する。
Data::Paginator
Data::Page互換のインターフェースに、Data::Pagesetと同等の機能を備えたモジュール。
Mooseベースならではのスッキリしたソースとなっている。ただ、この手の小さな機能を提供するライブラリにMooseは重いように思う。
Data::SimplePaginator
my $paginator = Data::SimplePaginator->new($number_per_page, @data); foreach ( $paginator->page($now_page) ) { print $_; }
与えたリストから指定したページ分の要素を切り出す機能に特化したモジュール。ページ遷移に関わる機能などはすっぱりと省かれている。