CakePHP1.3で作る会員管理システム(23) 検索とPagination
検索とPagination
で、検索しつつ Pagination する部分ですが、ちょっとややこしくて、一気に全部書くと訳が分からないので、仮にメールアドレスだけで検索する場合を最初に考えます。
普通に「検索」ボタンで検索した場合は
$this->data['Member']['email']
に値が渡ってきます。
一方 paginate で次へ、とかページ数をクリックした場合は、
$this->passedArgs['email']
に値が渡ってきます。
これをふまえて考えると、
まず、ボタンかリンクかで判別して渡ってきた値を変数に入れます。
if (!empty($this->data)) { $email = $this->data['Member']['email']; } else { $email = urldecode($this->passedArgs['email']); }
ボタンできた場合はいいですが、リンクで来た場合は$this->data['Member']に値が入っていないので、入れ直します。
if (isset($email)) { $this->data['Member']['email'] = $email; }
前回ビューで作った、peginator に検索キーワードを渡すためのオプションに値を設定します。
$searchword = array( "email" => urlencode("$email"), );
検索のクエリーの条件をセットします。
$conditions = array("Member.email LIKE" => "%$email%");
条件を使って検索してビューに渡します。
$data = $this->paginate('Member', $conditions); $this->set('searchword', $searchword); $this->set("members", $data);
基本的にはこの流れでいきます。
やっかいなのは日付データです。年月日を分割したり、結合したり、しないといけません。
ボタンから来た時は年月日の配列になってるので、そのまま入れて、リンクから来た時は文字列になってるのでsplitしたものを配列に入れます。
if (!empty($this->data)) { $f = $this->data['Member']['from']; $t = $this->data['Member']['to']; } else { list($f['year'], $f['month'], $f['day']) = preg_split("/-/", $this->passedArgs['from']); list($t['year'], $t['month'], $t['day']) = preg_split("/-/", $this->passedArgs['to']); }
同じように $this->data に戻しておきます。
$this->data['Member']['from'] = $f; $this->data['Member']['to'] = $t;
conditions や searchword 用には結合したものを使います。
$from = $f['year']."-".$f['month']."-".$f['day']; $to = $t['year']."-".$t['month']."-".$t['day'];
こんな感じになります。
$searchword = array( "from" => urlencode("$from"), "to" => urlencode("$to"), ); $conditions = array("Member.created BETWEEN ? AND ?" => array($from,$to));
で、存在しない日付とかを入れると思いっきりエラーになるので、日付データのチェックを別途 function を作って入れておきます。
こんな感じで。
function _from_to_check($f, $t) { if (!preg_match("/^[0-9]{4}$/", $f['year'])) {return false;} if (!preg_match("/^[0-9]{2}$/", $f['month'])) {return false;} if (!preg_match("/^[0-9]{2}$/", $f['day'])) {return false;} if (!preg_match("/^[0-9]{4}$/", $t['year'])) {return false;} if (!preg_match("/^[0-9]{2}$/", $t['month'])) {return false;} if (!preg_match("/^[0-9]{2}$/", $t['day'])) {return false;} if (!checkdate($f['month'], $f['day'], $f['year'])) {return false;} if (!checkdate($t['month'], $t['day'], $t['year'])) {return false;} return true; }
ここまでを整理するとこうなります。
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']; }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); } } } 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; } $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"); } $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')); }