cakephp のsearch pluginを使ってみる

Cakephp Search Plugin

http://cakedc.com/downloads/view/cakephp_search_plugin

前はgitからダウンロードできた気がしますが、URL忘れました。$2払わないといけないのかも。

わかりました。https://github.com/CakeDC/search

基本的な使い方は、readme.mdやらを見ればわかると思います。

ただ、URLはnamedが基本的な使い方のようで、自分的にはどうも気持がわるいURLになります。

GET方式で使ってみたときのメモ。

まずはモデルから。

たとえばイベントモデルがあったとして、キーワードで検索できるようにHABTMがリレーションされているとして、

public $actsAs = array('Search.Searchable');
public $filterArgs = array(
array('name' => 'title', 'type' => 'like'),
array('name' => 'status', 'type' => 'value'),
array('name' => 'area_id', 'type' => 'value'),
array('name' => 'search', 'type' => 'like', 'field' => 'Event.contents'),
array('name' => 'Keywords', 'type' => 'subquery', 'method' => 'findByKeywords', 'field' => 'Event.id'),
);

public function findByKeywords($data = array()) {
$this->EventKeyword->Behaviors->attach('Containable', array('autoFields' => false));
$this->EventKeyword->Behaviors->attach('Search.Searchable');
$query = $this->EventKeyword->getQuery('all', array(
'conditions' => array('EventKeyword.keyword_id' => $data['Keywords']),
'fields' => array('event_id'),
'contain' => array('Keyword')
));
//pr($query);exit;
return $query;
}


コントローラーには、

public $components = array('Search.Prg');

public $presetVars = array(
array('field' => 'title', 'type' => 'value'),
array('field' => 'Keywords', 'type' => 'value'),//チェックボックスでもvalueとすれば | でjoinされない。
);

//getのときはこんな感じに
$params = $this->Prg->exclude($this->params['url'],array('ext','url')); //不要なパラメーターを取り除いてくれるらいしい
$params = $this->Prg->serializeParams($params);//どうもこれを使うっぽい。
$this->data['Event'] = $params; //次ページでもフォームが選択された状態になるように。。
$this->paginate['conditions'] = $this->Event->parseCriteria($params); //ここはPOSTでも同じ。
/*
//post
$this->Prg->commonProcess();
$this->paginate['conditions'] = $this->Event->parseCriteria($this->passedArgs);
*
*/

$this->set('events', $this->paginate());
$this->set('keywords', $this->Event->Keyword->find('list'));



で、viewは特になにもしてないですが。

echo $form->create('Event', array(
'url' =>array('action' => 'search'),
'type'=>'get'
));
echo $this->Form->input('title', array('type' => 'text'));
echo $this->Form->input('Keywords', array(
'type' => 'select',
'multiple' => 'checkbox',
'options' => $keywords,
));
echo $form->submit('検索', array('div' => false));
echo $form->end();


で、ここまででGETでちゃんとできてるはずなので、あとはpagingをどうするか?
PEARのpagerを使いました。

bootstrap.phpにでもpearへのインクルードパスを通す。

// Pear
define('PearDIR',realpath(ROOT.'/../pear'));
set_include_path(get_include_path() . PATH_SEPARATOR .PearDIR);


elemetnにpear_pager.ctpなんかを作ってみる。

$url = $this->params['url'];
unset($url['url']);
unset($url['ext']);
require_once 'Pager/Pager.php';
$total = $paginator->counter(array('format' => '%count%'));
$params = array(
'mode' => 'sliding',
'perPage' => 20,
'delta' => 4,//現在のページの前後に表示するページ番号の数
'separator' => '',
'curPageLinkClassName' => 'current',
'prevImg' => '« 前へ',
'nextImg' => '次へ »',
'totalItems' => $total,//ページ付けするアイテムの数を指定
'urlVar' =>'page',
'path' => '',
'append' => true,
'fileName' => Router::url('/',true).$this->params['url']['url'],
'fixFileName' =>false,
'importQuery' =>false,
'extraVars' =>$url,

);

$pager = Pager::factory($params);

$links = $pager->getLinks();
$page_range = $pager->getPageRangeByPageId();
$page_range = range($page_range[0], $page_range[1]);
$link = '';
if ($links['pages'] != '') {
// 前のページ
if ($links['back'] != '') {
// クラスを付ける
$link .= str_replace(' } else {
$link .= ''.$pager->getOption('prevImg').'';
}
// 最初のページ
if ($links['first'] != '' && !in_array(1, $page_range)) {
$link .= $links['first'].'....';
}
// ページ
$link .= $links['pages'];
// 最後のページ
if ($links['last'] != '' && !in_array($pager->numPages(), $page_range)) {
$link .= '....'.$links['last'];
}
// 次のページ
if ($links['next'] != '') {
// クラスを付ける
$link .= str_replace('
} else {
$link .= ''.$pager->getOption('nextImg').'';
}
}
?>




とこんな感じでget方式で search plugin が使えました。