PCがあれば何でもできる!

へっぽこアラサープログラマーが、覚えたての知識を得意げにお届けします

【CakePHP 2.x】Paginatorコンポ―ネントのorderやlimitの設定が効かずに困った話

CakePHP Cookbook 2.x ドキュメントを見て書いてみたのですが、orderやlimitの設定をしても、デフォルトの設定で動いてしまい、だいぶハマりました^^;

環境

  • PHP 5.3.29
  • CakePHP 2.6.3

最初に書いたコード

<?php
class HogesController extends AppController {
  //Paginatorコンポーネントを読み込み
  public $components = array('Paginator');

  //$pagenateに検索条件を設定
  public $pagenate = array(
    'limit' => 10,
    'maxLimit' => 10,
    'order' => array('Hoge.modified' => 'desc')
  );

  public function index() {
    //paginateメソッドでデータ検索
    $this->set('hoges', $this->Paginator->paginate('Hoge'));
  }
}

結果(失敗)

想定では、クエリにLIMIT 10ORDER BYが入るはずが

SELECT `Hoge`.`id`, `Hoge`.`modified`
FROM `hoge`.`hoges` AS `Hoge` 
WHERE 1 = 1
LIMIT 20

全く設定が効いてない。。。orz

PaginatorComponentのソースを追って見た

ネットで調べても解決策が見つからず埒が明かないので、PaginatorComponentのソースを追って見ることに。

そしてわかったのは、

  • Controllerに定義した$pagenateにはアクセスしていない。
  • 設定をコンポーネントに反映させるには、以下の3つのタイミングがある。
    1. コンポーネントのコンストラクタの引数に渡す。
    2. コンポーネントのインスタンスの内部変数を書き換える。
    3. リクエスト時にパラメータとして渡す。(今回は説明を省きます)

1. コンポーネントのコンストラクタの引数に渡す。

コンストラクタの引数に渡すには、コンポーネント読み込みのコードを以下のようにします。

<?php
class HogesController extends AppController {
  //Paginatorコンポーネントを読み込み(ここに引数を入れる)
  public $components = array(
    'Paginator' => array(
      'limit' => 10,
      'maxLimit' => 10,
      'order' => array('Hoge.modified' => 'desc')
    )
  );

  public function index() {
    //paginateメソッドでデータ検索
    $this->set('hoges', $this->Paginator->paginate('Hoge'));
  }
}

結果

SELECT `Hoge`.`id`, `Hoge`.`modified`
FROM `hoge`.`hoges` AS `Hoge` 
WHERE 1 = 1
ORDER BY `Hoge`.'modified' desc
LIMIT 10

バッチリ!

2. コンポーネントのインスタンスの内部変数を書き換える。

コンポーネント内部では$settingというpublic変数に設定値が格納されています。
それを書き換えてあげればOKです。

<?php
class HogesController extends AppController {
  //Paginatorコンポーネントを読み込み
  public $components = array('Paginator');

  public function index() {
    //内部変数を書き換え
    public $this->Paginator->settings = array(
      'limit' => 10,
      'maxLimit' => 10,
      'order' => array('Hoge.modified' => 'desc')
    );

    //paginateメソッドでデータ検索
    $this->set('hoges', $this->Paginator->paginate('Hoge'));
  }
}

結果

SELECT `Hoge`.`id`, `Hoge`.`modified`
FROM `hoge`.`hoges` AS `Hoge` 
WHERE 1 = 1
ORDER BY `Hoge`.'modified' desc
LIMIT 10

問題なし!

好みと状況に応じて使い分けてください!