jqGridとPHPとZend_Dbでテーブルを検索する(JSONによるAjax)
建設予定地
とりあえずの目次
- てっとり早く済ませたい人は
- はじめるまえに
- jqGridの検索は3種類ある
- Filter
- Single
- Multi
- 3種類対応
2010/12/07 追記
ちょっと手が回っていなくて、このまま未完のまま放置させてもらいます。
てっとり早く済ませたい人は
jqGridの開発元が販売しているjqGrid for PHPを買うがよろし。
そんなに高くないのにZend_Db依存から抜け出せるはPHPだけで完結できるはで仕事で使うにはよさそうです。
え?
残念ながらぼくは買っていません。
予算申請するのが怖いのです。はい。
次の案件がうまくいったら予算申請するんだっ
はじめるまえに
この記事は以下の道具を使用しています。
※ライブラリでもフレームワークでもないし。なんて書けばいいのかわからないから道具。
PHP, Zend_Db
MySQL
jQuery, jQuery UI, jqGrid
jqGridの検索は3種類ある
wiki:jqgriddocsのSearchingにToolbar,Custome,Single,Advance(Multiple)って4種類あるんだけれど、ToolbarとCustomeは多分同じ動きをする。(はい、試していませんw)
この記事ではjqGridの検索を以下の3種類に分けて考えてみる。
- Filter (filterToolbar, filterGrid)
- Single (searchGrid)
- Multie (searchGrid with multipleSearch=true)
3種類対応
してません。週末にちゃんとしたコードを書きます。
載せられない部分を削ったら素敵な感じになりました。
<?php /* common/common.php で$db = Zend_Db_Abstractを作っています。 */ require_once('common/common.php'); // ここらへんにユーザー認証系のコードを書いています。 // GETとPOSTと区別するかを設定 // jqGrid.mtype = (get | post) $req = $_POST; // $_GET, $_POST, $_REQUEST // 一度に表示する件数と現在のページを設定 $page = isset($req['page']) ? $req['page'] : 1; $limit = isset($req['rows']) ? $req['rows'] : 25; // ソートに関する設定 $sidx = isset($req['sidx']) ? $req['sidx'] : ''; // order by $sidx $sord $sord = isset($req['sord']) ? $req['sord'] : 'asc'; // asc, desc // 検索用のデータが設定されているかどうか // 検索(true | false) $s = isset($req['_search']) ? $req['_search']: false; $table = 'TABLE_NAME'; $select = $db->select(); // ここでアクセス権限関係のWHERE句を追加しています。 // Zend_Db_Selectで複雑な検索条件の設定方法については // Idea of Zend_Db_Select nested where clause // という記事を書いているので読んでね。 /* ORDER BY * $sidxは field,field,field かもしれない、その場合は分割する必要がある。 * field asc, field asc, field asc となる * * まぁ、僕には関係ありませんけれどね。 */ if ($sidx) { $select->order(trim($sidx . ' ' . $sord)); } /* * あ。。 * 使わないからmultipleSearch以外のコード消しちゃってる。 * しかも、中途半端に削っているからエラー処理がめちゃくちゃ。 * 週末ぐらいに掲載できるコードを探してきます。 */ // multipleSearch:true のとき /* * ["_search"] => "true" * ["filters"] => '{"groupOp":"AND","rules":[{"field":"name","op":"eq","data":""}, {...}, ...]}' * * filtersはJSONです。PHPでいうところにStringです。 * * json_decodeを使用するためには、文字コードがUTF-8になってなくてはいけない。 * jqGridからPOSTされるデータは、基本的にはUTF-8です。 * ただし、レンサバの設定で問答無用にEUC-JPへ変換されていなければ。 */ $filters = isset($req['filters']) ? $req['filters'] : ''; if ($filters) { $filters = json_decode($filters); } /* * SingleとMultiの場合には条件が設定できる * filtersのなかのrulesのop項目です。 */ $operator = array( eq => array('=' , '', ''), // 等しい ne => array('<>' , '', ''), // 等しくない lt => array('<' , '', ''), // 〜より少ない le => array('<=' , '', ''), // 〜以下 gt => array('>' , '', ''), // 〜より大きい ge => array('>=' , '', ''), // 〜以上 bw => array('LIKE', '' , '%'), // 〜で始まる( val%) bn => array('NOT LIKE', '', '%'), // 〜で始まらない in => array('IN', '(', ')'), // 〜が含まれる ni => array('NOT IN', '(', ')'), ew => array('LIKE', '%', '' ), // 〜で終わる(%val ) en => array('NOT LIKE', '%', ''), cn => array('LIKE', '%', '%'), // 〜を含む (%val%) nc => array('NOT LIKE', '%', '%') ); $groupOp = $filters->groupOp; // (AND | OR) /* * $rule->op はちゃんとチェックしたほうがいいかもね。 * * * 検索条件的にワイルドカートが入るとまずい場合は * ちゃんと各自エスケープしてね */ foreach ( $filters->rules as $rule ) { $nest2[] = $db->quoteInto($rule->field . ' ' . $operator[$rule->op][0] . ' ?', $operator[$rule->op][1] . $rule->data . $operator[$rule->op][2]); } if ($groupOp == 'AND') { $nest2 = implode(' AND ', $nest2); $select->where($nest2); } else if ($groupOp == 'OR') { $nest2 = implode(' OR ', $nest2); $select->where($nest2); } /** * 条件に合致する総数を取得 **/ $select_count = $select; $select_count->from($table, 'count(*)'); $count = $db->fetchOne($select_count); $select->reset( Zend_Db_Select::COLUMNS); $select->reset( Zend_Db_Select::FROM ); /** * 総ページ数を取得 **/ if ( $count > 0) { $total_pages = ceil($count/$limit); } else { $total_pages = 0; } /** * データ取得用SQL作成 **/ // SQL文用パラメータ生成(limit用) if ($page > $total_pages) {$page=$total_pages;} $start = $limit*$page - $limit; $select->from($table, array('ID', 'ここにfiled名を書いていく、式でもいいけれど')) ->limitPage($page, $limit); // データ取得 $rows = $db->fetchAll($select); /** * 戻り値生成 **/ $ret->page = $page; // $req['page'] $ret->total = $total_pages; $ret->records = (int)$count; /* * id はユニーク値がいいとおもうよ */ $i = 0; foreach ($rows as $key => $value) { $ret->rows[$i]['id'] = $value['ID']; $ret->rows[$i]['cell'] = array_values($value ); $i++; } $json = json_encode($ret); header('Content-Type: application/json; charset=UTF-8'); echo $json;