検索とPaginationとHABTM
で、さらにやっかいなのが、ここに「好きな物」のチェックボックスの複数選択検索を入れる場合です。
HABTMの関連テーブルですね。
一体どうすりゃいいんでしょうか。ということで相当悩みました。
結論としては、一旦その「好きな物」を選択している会員のIDを全部取り出して、そいつを条件に入れちゃえばいいんじゃなかろうかと。
クエリーのイメージはこんな感じ。
SELECT m.id FROM members m WHERE m.id IN
(SELECT member_id FROM members_favorites mf WHERE mf.favorite_id IN (1,2));
つまり()内のSELECTの部分をあらかじめデータ取得しておけばいいと。
ということでこうなった。
$fid = $this->Member->MembersFavorite->find('list', array(
'order'=>array('MembersFavorite.member_id DESC'),
'group'=>array('MembersFavorite.member_id'),
'fields' => array('MembersFavorite.member_id'),
'conditions' => array('MembersFavorite.favorite_id' => $favorite_id)
));
$conditions = array("Member.id" => $fid);
$data = $this->paginate('Member', $conditions);
これは上記ではIN ()の中はSELECT文になっているが、CakePHPの文法だとそれは入らないようなので、実際に配列が入る。こんな感じになる。
SELECT `MembersFavorite`.`id`, `MembersFavorite`.`member_id`
FROM `members_favorites` AS `MembersFavorite`
WHERE `MembersFavorite`.`favorite_id` IN (1, 2, 3)
GROUP BY `MembersFavorite`.`member_id`
ORDER BY `MembersFavorite`.`member_id` DESC
最終的にこうなりました。
function admin_search() {
$this->Member->recursive = 0;
if (!empty($this->data)) {
$f = $this->data['Member']['from'];
$t = $this->data['Member']['to'];
$email = $this->data['Member']['email'];
$type_id = $this->data['Member']['type_id'];
$favorite_id = $this->data['Member']['favorites'];
}else{
foreach ($this->passedArgs as $k => $v){
if ($k == 'from'){
list($f['year'], $f['month'], $f['day']) = preg_split("/-/", $v);
}elseif($k == 'to'){
list($t['year'], $t['month'], $t['day']) = preg_split("/-/", $v);
}elseif($k == 'email'){
$email = urldecode($v);
}elseif($k == 'type_id'){
$type_id = urldecode($v);
} elseif(preg_match("/^favorite_id_([0-9]+)$/", $k, $regs)) {
$favorite_id[$regs[1]] = $v;
}
}
}
if (isset($f) && isset($t)){
if ($this->_from_to_check($f, $t)) {
$from = $f['year']."-".$f['month']."-".$f['day'];
$to = $t['year']."-".$t['month']."-".$t['day'];
$this->data['Member']['from'] = $f;
$this->data['Member']['to'] = $t;
}
}
if(isset($email)){
$this->data['Member']['email'] = $email;
}
if(isset($type_id)){
$this->data['Member']['type_id'] = $type_id;
}
if (isset($favorite_id)){
$this->data['Member']['favorites'] = $favorite_id;
}
$searchword = array();
$conditions = array();
if (isset($from) && isset($to)){
$searchword = array(
"from" => urlencode($from),
"to" => urlencode($to),
);
$conditions = array("Member.created BETWEEN ? AND ?" => array($from,$to));
}
if (isset($email) && $email){
$searchword = $searchword + array(
"email" => urlencode("$email"),
);
$conditions = $conditions + array("Member.email LIKE" => "%$email%");
}
if (isset($type_id) && $type_id){
$searchword = $searchword + array(
"type_id" => urlencode("$type_id"),
);
$conditions = $conditions + array("Member.type_id" => $type_id);
}
if (isset($favorite_id) && $favorite_id){
foreach ($favorite_id as $k => $v){
$temp_favotite['favorite_id_'.$k] = $v;
}
$searchword = $searchword + $temp_favotite;
$fid = $this->Member->MembersFavorite->find('list', array(
'order'=>array('MembersFavorite.member_id DESC'),
'group'=>array('MembersFavorite.member_id'),
'fields' => array('MembersFavorite.member_id'),
'conditions' => array('MembersFavorite.favorite_id' => $favorite_id)
));
$conditions = $conditions + array("Member.id" => $fid);
}
$data = $this->paginate('Member', $conditions);
$this->set('searchword', $searchword);
$this->set("members", $data);
$favorites = $this->Member->Favorite->find('list');
$types = $this->Member->Type->find('list');
$this->set(compact('favorites','types'));
}