Real Blog

レジェンド鈴木が日々感じたことを哲学するブログ。書評、エッセイ、ポエムも書いてます。

cakephpのページング時の検索条件の引き継ぎ

cakephpではデフォルトでページングの機能をサポートしていますが、 ページ越しの検索条件の引き継ぎはサポートされていないようです。

cakephp ページング 検索条件引き継ぎ」等で検索すれば、既に何個かこの課題への解決方法が記載されたページがありますが、 コントローラーやビューを色々変更する必要があるものが多いようです。

なので今回はコントローラーへのコードの追加は1行だけ、ビューは変更なしで上記の課題が解決できるシンプルな方法を説明したいと思います。
cakephp.pngのサムネイル画像

考え方としては下記のようになっています。

1.検索条件を引き継ぐのではなく、POSTされたデータを引き継ぐ
2.引き継ぎはSESSIONで行う
3.ページングの判定は、 controller->params['named']['page']を見て行う

という感じです。

上記の処理をコンポーネントにまとめると、「コントローラーへのコード追加は1行だけ」が実現できます。

この方法の副産物としてページング上部に検索フォームがある(googleのような)場合、自動的にフォーム入力値も引き継ぐことができます。

以下実装例を記載します。

controller側
function index(){
	
	$this->PagingSupport->inheritPostData(); //$this->dataの値の引き継ぎが行われる
	
	$conditions = array();
	
	if( !empty( $this->data ) ){
		$conditions = $this->Article->getConditions( $this->data ); //検索フォームの入力値から conditions を取得
	}
	
	$this->set( 'articles', $this->paginate( 'Article', $conditions ) );
}


component側
/**
 * 既存のページング機能をサポートするコンポーネント
 */

class PagingSupportComponent extends Object {
	
	var $components = array('Session');
	
	var $_controller = null;
	
	var $_sessionName = '';
	
	function startup( & $controller ) {
    	$this->_controller = $controller;
		$this->_sessionName = $this->_getSessionName( $controller->params );
  	}
	
	/**
	 * controller->data の値の引き継ぎを行う
	 */
  	function inheritPostData(){
  		
		if( !empty( $this->_controller->data ) ){
			$this->Session->write( $this->_sessionName, $this->_controller->data );
		}
		elseif( !empty( $this->_controller->params['named']['page'] ) && $this->Session->check( $this->_sessionName ) ){
			$this->_controller->data = $this->Session->read( $this->_sessionName );
		}
		else{
			$this->Session->delete( $this->_sessionName );
		}	
  	}
	
	/**
	 * 現在引き継がれているPostDataを取得
	 * @param $params = array( 'controller' => ..., 'action' => ... )
	 * @return array
	 */
	function getInheritPostdata( $params ){
		if( $this->Session->check( $this->_getSessionName( $params ) ) ){
			return $this->Session->read( $this->_getSessionName( $params ) );
		}
		else{
			return null;
		}
	}
  	
	/**
	 * SESSIONに使用する名前を取得
	 */
	private function _getSessionName( $params ){
		return 'pagingSupport_' . $params['controller'] . $params['action'];
	}
}		
今回紹介したのはPOSTデータの場合ですが、少し工夫すれば同じ考え方でGETデータの場合も実装できると思います。
弊社の開発したシステムでのこのコードを使用しているので、気に入っていただけた方は是非使ってみてください。