tokuhirom's Blog

Amon2::Setup::Flavor::Large + Teng をもちいた簡単な掲示板の作成 その2『ページャーをつけよう』 〜 軽量フレームワークAmon2入門 (8) 〜

さて、掲示板をつくったとはいえ、これだけではおもしろくありませんね。

まずこの掲示板には重大な欠陥があります。具体的にいうと、ページングがされていません。
ウェブアプリケーションにおいてはページングは非常に重要な要素です。
なにかを一覧表示するページをつくるときに、ページングのことが思いうかばないようでは一人前のウェブエンジニアとはいえません。ページングを手抜きすると、あとあと重いページになって泣くことになるでしょう。ページングは最初の段階でいれておくのが結局は楽なのです(という自戒)。

さて、今回の掲示板では Teng をつかっているので非常にページャの実装が容易になっています。Teng ではページャ関連の実装はプラグインとなっていますから、Teng に Teng::Plugin::Pager をよみこませましょう。lib/MyBBS/DB.pm に以下のようにかきましょう。

package MyBBS::DB;
use strict;
use warnings;
use utf8;
use parent qw/Teng/;

__PACKAGE__->load_plugin('Pager');

1;

次に、このモジュールをよみこまなくてはいけませんから、lib/MyBBS.pm の sub db のあたりを以下のようにかきかえます。

use Teng;
use Teng::Schema::Loader;
use MyBBS::DB;
sub db {
    my $self = shift;
    if ( !defined $self->{db} ) {
        my $conf = $self->config->{'DBI'}
        or die "missing configuration for 'DBI'";
        my $dbh = $self->dbh;
        my $schema = Teng::Schema::Loader->load(
            namespace => 'MyBBS::DB',
            dbh       => $dbh,
            );
        $self->{db} = MyBBS::DB->new(
            dbh    => $dbh,
            schema => $schema,
            );
    }
    return $self->{db};
}

ここまでで Teng の側の準備はできましたから、つづいてはコントローラ側のコードをいじくりましょう。
前回、以下のようにかいたところがありますが

sub index {
    my ($class, $c) = @_;
    my @entries = $c->db->search('entry', {}, {order_by => 'id DESC'});
    $c->render('index.tt', { entries => \@entries});
}

これをちょっとかえるだけで OK です。

sub index {
    my ($class, $c) = @_;
    my $page = $c->req->param('page') || 1;
    my ($entries, $pager) = $c->db->search_with_pager('entry' => {}, {order_by => 'id DESC', page => $page, rows => 20});
    $c->render('index.tt', { entries => $entries, pager => $pager });
}

のようにすればいいでしょう。非常に簡単ですね。ここで $pager は Data::Page::NoTotalEntries クラスのインスタンスとなっています。このあたりの詳細については Teng::Plugin::Pager のドキュメントを参照してください。

さて、テンプレートの方の変更ですが、Amon2::Setup::Flavor::Large でスケルトンをつくると tmpl/pc/include/pager.tt というページャのためのテンプレートが自動生成されますので、以下のように tmpl/pc/index.tt をかえるだけでよいです。

[% WRAPPER 'include/layout.tt' %]

<form method="post" action="/entry/create">
    <fieldset>
        <div><textarea name="body"></textarea></div>
        <div><input type="submit" value="Post New Entry" class="btn primary" /></div>
    </fieldset>
</form>

[% FOR entry IN entries %]
    [% entry.id %]. [% entry.body %]<br />
[% END %]

[% INCLUDE 'include/pager.tt' WITH pager=pager %]

[% END %]

というわけで今回はページャをつけてみました。あまり派手な変更ではありませんが、Teng のプラグインの使い方などが体得できたことかとおもいます。