「Paginationのために(CakePHP 1.1から)1.2にアップグレードしたい」と言う人がいるほど、Paginationは便利なものです。今回はPaginationの紹介と、サンプルコードを3つ紹介いたします。
Webアプリに欠かせない「ページ繰り」は自前でやるのは面倒!
ページ繰りとは、「次のページ」や「前のページ」の基本的なリンクから、「1 2 3 4 5 …」といったページ番号でのリンクなどのことです(図1)。
複数のデータを列挙するWebアプリケーションでは、必ずと言っていいほどこのページ繰りが必要になります。
しかし、ページ繰りをすべて自前でやるのは意外に面倒で、加減算や除算を駆使した計算をずらずら書かないといけません。表示のときにも場合わけが必要で、1ページ目なら「前へ」はリンクしませんし、最後のページなら「次へ」はリンクしません。
「次へ」「前へ」だけならまだしも、ページ番号の列挙などになると、計算に加えて「最大で5件表示するけど5件に満たないとき」などの例外への対応も必要になります。さまざまなパターンの動作確認のためのデータの用意も手間ですね。
このようにすべてのケースに対応できるような汎用的なコードを書こうとすると結構大変なので、仕様を簡略化したり、場当たり的に行っていた場合も少なくないのではないでしょうか。
そんな面倒なページ繰りを、計算から表示までほぼ全て引き受けてくれるのが「Pagination」機構なのです。
Pagination例その1:基本のサンプルコード
もしPaginationのコードを見るのが初めてな場合、「えっ、これだけでいいの?」と驚くことでしょう。
Paginationはコントローラーでセットアップし、ビューで表示させます。まずはコントローラです。
次にビューです。PaginatorHelperで表示します。PaginatorHelperはコントローラーで指定しなくても読み込まれています。
たったこれだけで、前後のリンクとページ番号の列挙が完成しました。たとえば1ページ目を表示しようとして、最大3ページの場合、以下のようなHTMLが出力されます。
ブラウザ上の表示は図2のようになります。
「前へ」の表示がありませんが、1ページ目なので自動的に表示しないように処理されています。1ページ目でも何か表示したければprevメソッドの第三引数に文字列を渡せば1ページ目のときのみ出力されます。リンクは行われません。
また、ページ番号の列挙がspanで囲われていますが、これもnumbersメソッドへの引数によってliなどの要素にすることもできますし、適切にCSSをあてれば図1のように表示させることも可能です。
Pagination例その2:検索条件や取得フィールドなどを指定する
取得するレコードの検索条件の指定や、取得するフィールドの絞り込み、recusive値などを指定することもできます。
パラメータの形式はModel::find()メソッドの引数と同じです。
Pagination例その3:URLからのパラメータも引き継ぐ
URLから受け取ったパラメータを引き継ぎたいときは、ひと手間必要です。
例は、カテゴリーIdをURLから受け取れるようにして、http://example/sample/posts/123といったURLでアクセスする場合です。引き継ぎたい値をsetメソッドでビューに渡します。
ビュー側では、prev,next,numbersなどのメソッドの引数に引き継ぎたいパラメータを渡します。
出力結果は以下のようになります。
また、「array($category_id)」の部分を「array('category_id' => $category_id)」とすれば、URLは「/sample/posts/category_id:123/page:2」になります。全てのURLに対応するにはルーティングの設定が必要になることがありますが、不可能ではありません。ちょっと複雑ですが、Paginationの恩恵は大きいので、ぜひマスターしたいところです。
まだまだある、PaginatorHelperのメソッド群
Paginatorができるのは前後のリンクとページ番号だけではありません。PaginatorHelperのメソッド群を利用すればかなり複雑なページ繰り表示にも自由に対応できます。メソッド群の一部を表にしました。
counter() | 「1ページ目を表示 4ページ中」といった表示 |
current() | 現在のページ番号 |
first() | 最初のページへのリンク |
last() | 最後のページへのリンク |
hasNext() | 次のページがあるか (true or false) |
hasPrev() | 前のページがあるか (true or false) |
hasPage($page) | 指定のページ番号のページがあるか (true or false) |
$params | ページ数などの情報やパラメータが詰まった連想配列。例えば $paginator->params['paging']['Post']['count'] で件数を取得できる。 |
とくに$paginator->params変数の中身は、自由なページ繰り表示には欠かせませんので、var_dumpするなどして一度構造を確認しておくと良いでしょう。