CakePHP3のPaginateに表示可能ページ数を設定する

CakePHP3のPaginateで、表示できる最大ページ数を設定する方法をメモしておきます。

なぜ?

CakePHP3のPaginateは、
LIMITとOFFSETを使いページネーションを実現しています。

つまり、DBのレコード数が多くなり、OFFSETの値が大きくなればなるほど、
それだけサーバに負荷がかかってしまいます。

正しくINDEXを作っていれば、そんなに遅くならない、らしい。
ですが、DBのCPU独占をまずは止めたかったため、
今回Paginateを上書きしました X<

コピー

Paginate関連のファイルは2種あります。

  • vendor/cakephp/cakephp/src/Controller/Component/PaginatorComponent.php
  • vendor/cakephp/cakephp/src/View/Helper/PaginatorHelper.php

このファイルをそれぞれ、

  • src/Controller/Component/PaginatorComponent.php
  • src/View/Helper/PaginatorHelper.php

上記パスにコピーしてきます。

PaginatorComponent.phpの書き換え

まずはPaginatorComponent.phpを編集していきます。
エディタでsrc/Controller/Component/PaginatorComponent.phpを開いてください。

<?php
namespace App\Controller\Component;

// ...
?>

まずはnamespaceをCakeからAppへと書き換えます。

protected $_defaultConfig = [
  // ...
  'maxPage' => 100 // add
];

$_defaultConfigに新しくmaxPageを追加します。
この値が表示可能なページ数になります。
今回は初期値を100ページに設定します。

public function paginate($object, array $settings = [])
{
  // ...
  
  // $pageCount = (int)ceil($count / $limit);
  $pageCount = $options['maxPage']; // 書き換え

  // ...
}

paginateメソッドの$pageCountを
先ほど設定したmaxPageで上書きします。

以上がPaginatorComponent.phpの変更箇所です。

PaginatorHelper.phpの書き換え

次にPaginatorHelper.phpを書き換えていきます。
エディタでsrc/View/Helper/PaginatorHelper.phpを開いてください。

PaginatorComponent.phpと同様に、
PaginatorHelper.phpもnamespaceをAppに書き換えます。

<?php
namespace App\View\Helper;

//...
?>

次にhasNextメソッドを書き換えます。

public function hasNext($model = null)
{
  $params = $this->params($model);
  if( $params['page'] < $params['pageCount'] ){
    return $this->_hasPage($model, 'next');
  }else{
    return 0; // max page
  }
}

$this->paramsには
現在のページネーションの状態が格納されているようなので、
それを利用します。

$params[‘page’]は現在のページ数、
$params[‘pageCount’]は先ほど設定した、表示可能ページ数が格納されています。

表示可能ページ数より現在のページ数が小さくなければ、
0を返してページネーションのnextリンクを無効にします。

おわりに

以上の変更で、ページネーションを利用するときは自動的に、
変更を加えたsrcの方が読み込まれます。

表示可能な最大ページ数を変更したい場合は、
paginateを利用しているControllerで

$this->paginate['maxPage'] = 100;

上記のような感じで、
paginateのmaxPageに値を入れていただければ変更可能です。

Controllerで使用するPaginatorを切り替えたり、
上書きするにしてもコンポジションで実装する等、
やり方があると思いますが、今回はまるまる書き換えました XD