CakePHP1.3.6:ページネーション(Pagination)。

CakePHPで秀逸だなぁと思うのが、このページネーション。とってもスマートに書くことができる。Myznalaでもオレオレ流のページネーションを提供しているが、自分で書くとなるとそれなりに面倒くさい。

CakePHPでは、一覧表示画面に簡単なコードを追加するだけで、

  • ページの区切り
  • 前後のページへの移動
  • 特定のページへのジャンプ
  • 見出しクリックによるソート

ができてしまう。素晴らしい!!

前回のログのコードをベースに上の機能を追加する。コントローラーとindexアクションのテンプレート(index.ctp)を変えるだけでよい。

コントローラーの変更

$paginateというメンバー変数にオプションを定義する。
Sort+Directionというオプションがあるようだが動かないので、orderオプションで指定した。
修正するアクションはindexのみ。

<?php
require_once '../vendors/MyConverter.class.php';

class CustomersController extends AppController{
	public $name = 'Customers';
	public $layout = 'myznala';
	
	/*
	 * Paginatorの定義
	 */
	public $paginate = array(
		'page'=>1,
		'conditions'=>array(),
		'fields'=>array('id','name','zip','address','tel','timestamp'),
		'order'=>array('timestamp'=>'desc'),
		'limit'=>5,
		'recursive'=>0
	);
	
	/**
	 * 
	 * 初期画面(一覧表示)
	 */
	function index(){
		$this->set('title_for_layout', "顧客の一覧");
		$req=null;
		if(!empty($this->data)){
			//サニタイズ
			$req = MyConverter::getRequestParams($this->data["Customer"]);
			//絞り込みの場合には、コンディションを書き換える。
			$this->paginate['conditions'] = array('Customer.name like ?' => array("%{$req["name"]}%"));
		}
		$data = $this->paginate();
		
		$this->set('data',$data);
	}
	
	/**
	 * 
	 * データの追加
	 * 
	 */
	function add(){
		$this->set('title_for_layout', "顧客の登録");
		if(!empty($this->data)){
			// サニタイズ
			$this->data["Customer"] = MyConverter::getRequestParams($this->data["Customer"]);
			// 登録
			$this->Customer->save($this->data);
			if($this->Customer->validates()){
				// 登録できたらリダイレクト
				$this->redirect('.');
			}
		}
	}
	
	/**
	 * 
	 * データの照会
	 * $paramsにIdが入ってくる。
	 * 
	 */
	function show($param){
		$this->set('title_for_layout', "顧客の詳細");
		$result=null;
		if(!empty($param)){
			// Idフィールドによる検索
			$this->data=$this->Customer->findById($param);
			if(!$this->data){
				// 存在しないIDを参照された場合。
				$this->Session->setFlash('存在しません');
				$this->redirect('.');
			}
		}
		$this->set('data',$this->data);
	}

	/**
	 * 
	 * データの更新
	 * 
	 */
	function edit($param){
		$this->set('title_for_layout', "顧客情報の更新");
		// データの更新
		if(!empty($this->data)){
			// サニタイズ
			$this->data["Customer"] = MyConverter::getRequestParams($this->data["Customer"]);
			// Idフィールドによる検索
			$check=$this->Customer->findById($param);
			if(!$check){
				// 存在しないIDを更新しようとした場合。
				$this->Session->setFlash('存在しません');
				$this->redirect('.');
			}else{
				// 更新
				$this->Customer->save($this->data);
				if($this->Customer->validates()){
					// 更新できたらリダイレクト
					$this->redirect('.');
				}
			}
		// 更新データのセット(初期値)
		}else{
			if(!empty($param)){
				// Idフィールドによる検索
				$check=$this->Customer->findById($param);
				if(!$check){
					// 存在しないIDを更新しようとした場合。
					$this->Session->setFlash('存在しません');
					$this->redirect('.');
				}else{
					// Idフィールドによる検索
					$this->data=$this->Customer->findById($param);
				}
			}
		}
		// エラーの場合も通るようにする
		$this->set('data',$this->data);
	}

	/**
	 * 
	 * データの削除
	 * 
	 */
	function delete($param){
		if(!empty($param)){
			$check=$this->Customer->findById($param);
			if(!$check){
				// 存在しないIDを削除しようとした場合。
				$this->Session->setFlash('存在しません');
			}else{
				// Idフィールドによる削除
				$this->data=$this->Customer->delete($param);
			}
			$this->redirect('.');
		}
	}
	
}
?>

ビューの修正

index.ctpを以下のように修正する。
どうも、customersを最初に呼び出したときに、照会ページと登録ページへのアンカーからcustomersが抜けてしまう(ページネータを使う前から)。
そこで、アンカーをHTMLヘルパーで生成するようにしてみた。

<h2>顧客の一覧</h2>
<br>
名前で絞り込みをします。
<?php 
// 絞り込み用フォーム
echo $form->create('Customer',array('type'=>'post','action'=>'.'));
echo $form->text('Customer.name', array('size' => 10));
echo $form->end('送信');
?>

<?php 
// ページネーション
echo $paginator->numbers(
	array(
		'before'=>$paginator->hasPrev() ? $paginator->first('<<').' ' : '',
		'after'=>$paginator->hasNext() ? ' '.$paginator->last('>>') : '',
		'modulus'=>4,
		'separator'=>' '
	)
);
?>

<table>
<tr>
	<th><?php echo $paginator->sort('ID','id') ?></th>
	<th><?php echo $paginator->sort('名前','name') ?></th>
	<th><?php echo $paginator->sort('郵便番号','zip') ?></th>
	<th><?php echo $paginator->sort('住所','address') ?></th>
	<th><?php echo $paginator->sort('電話','tel') ?></th>
	<th><?php echo $paginator->sort('更新日','timestamp') ?></th>
</tr>
<?php 
	foreach ($data as $arr){
		echo '<tr>';
		echo '<td>'.$html->link($arr['Customer']['id'],
  				array('controller'=>'customers', 'action'=>'show',$arr['Customer']['id'])).'</td>';
		echo "<td>{$arr['Customer']['name']}</td>";
		echo "<td>{$arr['Customer']['zip']}</td>";
		echo "<td>{$arr['Customer']['address']}</td>";
		echo "<td>{$arr['Customer']['tel']}</td>";
		echo "<td>{$arr['Customer']['timestamp']}</td>";
		echo '</tr>';
	}
?>
</table>
<?php
echo $html->link('登録',
  array('controller'=>'customers', 'action'=>'add'));
?>