CakePHPクッキング

ページ送り

開発環境:CakePHP2.5.1

GoogleやYahooなどの検索結果のページでよく見る1ページ目、2ページ目、前のページヘ、次のページヘなどのページ送り。
これを素のPHPで書こうとすると結構面倒ですが、CakePHPのPaginatorコンポーネントおよびPaginatorヘルパーを使えば簡単に書くことができます。

コントローラーでの準備

まずは、コントローラーでPaginatorコンポーネントを指定し、ページ送りのデフォルト条件を指定します。

<?php
public $components = array('Paginator');

public $paginate = array(
    'limit' => 10,
    'order' => array(
        'Post.id' => 'desc'
    )
);
?>

そして、ページ送りを使うアクション内で、設定をセットし、PaginatorコンポーネントのpaginateメソッドにModelを指定してデータを取得します。

<?php
public function index() {
    $this->Paginator->settings = $this->paginate;
    $data = $this->Paginator->paginate('Post');
    $this->set(compact('data'));
}
?>

ビューの書き方

ビュー側のPaginatorヘルパーは様々なメソッドが用意されています。

1|2|3|などのページ番号のリンク

<?php echo $this->Paginator->numbers(); ?>

前へ・次へのリンク

<?php echo $this->Paginator->prev('前へ'); ?>
<?php echo $this->Paginator->next('次へ'); ?>

ページネーションの効率的な書き方

上記のようなコードをビューにそのまま書いても問題ないのですが、ページ送りの機能を他のページでも使う場合はエレメントにまとめてしまうとメンテナンスがラクになり、コードがすっきりします。
例えば、app/View/Elements/paginator.ctpというファイルを作り、その中に上記のコードを書いておきます。
それをビュー側から次のように呼び出せば、ビューにそのまま書くのと同じ状態が作れます。

<?php echo $this->element('paginator'); ?>

検索条件を引き継いだページ送り

検索結果のgetパラメータをページ送りで引き継ぐ方法です。
これは特に何も設定しなくてもCakePHP側が自動でそのようにやってくれます。
唯一行うのは、ビュー側の検索フォームをgetで渡すことくらいです。

<?php
echo $this->Form->create('Post', array('url' => '/', 'type' => 'get'));
echo $this->Form->input('title');
echo $this->Form->end('Search');
?>

こうすると、ページ送りのURLは /page:2?title=hoge のようになります。

ページ送りを?page=2のようにする方法

デフォルトの状態だとページ数の部分は/page:2のような感じになっていますが、これを?page=2のようなパラメータで渡したい場合はコントローラーの設定で次のようにします。

<?php
public $paginate = array(
    'paramType' => 'querystring',
);

paramTypeにquerystringを設定することで期待通りの形式のURLが生成されます。

ページ送りで重複データを省く

ページネーションで重複データを省くにはちょっと注意が必要です。
ポイントはDISTINCTを利用するのではなく、GROUP BYを利用することです。
詳しくは「ページネーションではDISTINCTではなく、GROUP BYを使う」をご覧ください。

自動でどんどん読み込むページ送り

FacebookやTwitterなどでよく見るスクロールしていくと次から次に表示されるタイプのもの。
あれを実現するにはJQueryを使うことで対応できます。
インフィニティスクロールを使った無限スクロールのやり方はこちらからご覧ください。

paginateのパラメータをモデルに書いて効率的に管理

最初に紹介したようにコントローラーにpaginateパラメータを設定するのが一般的ですが、一つのコントローラーに複数のページ送り機能があったりするときなど、ちょっと面倒になるのに加え、コントローラーのコード量も増えていきます。
それらを防ぐためにもpaginateのパラメータをモデルに書いてしまうのもおすすめです。

モデル側にはコントローラーで書いていた時と同様の書き方で、

<?php
class Sample extends AppModel
{
    public $paginate = array(
        'conditions' => array(
            'Sample.flg' => 0,
        ),
        'limit' => 30,
        'order' => array(
            'Sample.id' => 'desc'
        )
    );
}

このように書いておきます。

一方、コントローラー側には、

<?php
App::uses('AppController', 'Controller');

class SampleController extends AppController {
    public $uses = array('Sample');
    public $components = array('Paginator');
    public $paginate;

    public function index() {
        $this->paginate = $this->Sample->paginate;
        $this->Paginator->settings = $this->paginate;
        $samples = $this->Paginator->paginate('Sample');
    }

このようにモデル側のpaginateパラメータを呼び出して、本来のpaginatorにセットすれば完成です。

WordPressとCakePHPの共存

サイトを作るのに便利なWordPress。プラグインも数多く用意されて

サイトマップの作成方法

Googleのウェブマスターツールに渡すためのサイトマップの作成方法で

INSERTしたIDを取得する

データを保存した後にINSERTされたデータのIDを使って何かの処理を

ファイルの存在確認やフォルダー内のファイル一覧取得

特定のファイルの存在を確認したい場合や特定のフォルダー内にあるファイル

リンクの最後に常にスラッシュをつける方法

URLの最後に常にスラッシュをつけるかつけないかを統一する方法は、UR

countやsumを使う時のフィールド名を指定する

CakePHPでcountやsumなどを使う場合、ちょっとした工夫が必

Formの便利な使い方

問い合わせフォームや会員機能など、WEBサイトを作る際に必ず必要になる

ヘルパーをオーバーライドする

CakePHPで便利な機能が詰まったヘルパーですが、時々もう少しこうだ

特定の時だけSQLの条件を追加するならSet::mergeを使う

SQLの条件を追加したい時に使うのがarray_mergeなどですが、

ページネーションではDISTINCTではなく、GROUP BYを使う

重複したデータを省く時に使うDISTINCTですが、ページ送りで使う時

Model内で別のModelを呼び出す

モデル内で別のモデルを使いたいケースがあった場合、次のようにすることで

CakePHPでGoogleAnalyticsAPIを使う

CakePHPでGoogleAnalyticsを使う方法について見てい

独自のfindを定義するfindMethods

findをより便利に、よりスッキリ書くのに、findMethodsを使

TCPDFを使ってCakePHPでPDFを作成

CakePHPでPDFを作成するには幾つかの方法がありますが、今回はT

JavaScriptをコードの最下部に配置

SEOの観点からJavaScriptのコードは一番下に記述したいところ

無限スクロールをさせる

TwitterやFacebookのタイムラインを見ていて、ページの下に

PHPExcelの導入

ExcelにDBのデータを表示して一覧を作ったり、請求書などのフォーマ

Warning: SplFileInfo::openFile〜の警告が表示されたら

ShellとWEBの両方で同一のModelを呼び出す時に「Warnin

連結されていないデータを抽出

通常、テーブルを連結してデータを取得するには、アソシエーションを利用し

データを取得する

データを取得したい時に少し変わった条件で取得したい場合があります。

PAGE TOP ↑