具体的には、都道府県フィールドなどに「県[SPACE]山」などと入力した場合に、これまでのモノはWHERE pref like '%県 山%'というクエリしか発行せず結果は0件になりますが、これをWHERE pref like '%県%' AND pref like '%山%'というようなクエリを発行するようにして「山形県」「山梨県」「岡山県」…などを検索できるようにしたい、ということです。
↑でもちらっと触れたように、この機能?はココの合併データベース検索アプリではほとんど必要ないものかもしれません。もしくはANDではなくORにした方がよいのではないか?という気もしないでもありません。が、まあ大元のスクリプトには実装されてることですし、とりあえず作ってみたいとおもいます。
まず入力値ですが、これは次のように規定します。
半角または全角スペースで区切られた単語(文字)をAND検索する
連続する半角・全角スペースは1個とみなす
で、これをそのままヴァリデーションとして実装します。
//pregに/uオプションを付けても、\s(空白文字)に全角SPはマッチしない
foreach ($this->input->post('condition') as $key => $str)
{
$conditions[$key] = trim(preg_replace("/[ \s]+/u", ' ', $str));
}
preg_replaceに/uオプション(unicode対応)をつけてホワイトスペース文字(\s)の連続を半角スペースに置き換えて両端をtrimしています。これをフィールド分(今のところ3つ:都道府県、新市町村、旧市町村)繰り返しているだけです。
但し全角スペースに関してはコメントにあるように、/uオプションでも空白文字としては認識していないようだったので、文字クラス内に記述しました。なので正規表現部分の空白は全角スペース、置換文字の方の空白は半角スペースです。
次に実際のクエリを組み立てている部分ですが、元々は連想配列をアクティブレコードのlike()に渡していた部分を書き換えます。
修正前 controller/search.php(検索オブジェクトクラスファイル)
function where()
{
$CI =& get_instance();
$CI->db->like($this->getCriteria());
}
修正後 controller/search.php(検索オブジェクトクラスファイル)
function where()
{
$CI =& get_instance();
foreach ($this->getCriteria() as $field => $condition)
{
$sameFieldConditions = explode(" ", $condition);
foreach ($sameFieldConditions as $cond)
{
$CI->db->like($field, $cond);
}
}
}
結局単に配列を渡していただけの部分がforeachの入れ子になってしまいました。やってることは見てのとおり単純なことなんですが、修正前と比べるとやはりかなりアレだなぁ?という印象が…。
でもまあ基本的にはこれだけの変更でフィールド内でのAND検索が実装できたわけで、こういう部分は手続き型でダラダラ書いているよりはわかりやすいと感じました。
検索画面
まずこんな感じで適当に半角・全角スペースを混ぜて検索してみます。
※赤枠:全角スペース、緑枠:半角スペース(300%拡大)
表示結果
↑のイメージのように、前後のスペースが削除され連続スペースも一つになっているのがわかるとおもいます。クエリも各フィールドごとにANDで出力されているようです。もちろん検索結果も正常です。
ということでおもっていたよりも意外にあっさりとできた感じでした。次回は合併日の検索について書こうとおもいます。
ラベル:codeigniter PHP