検索機能の作り方 -PHP-

PHP

検索、、難しそうだな~~と思ってましたが
勇気を持って挑んだら形になりましたキラキラ

しかも自分で作るとなると完璧主義がぐいぐい出て
スペース区切りとか半角カナの対応とかいろいろしたチューリップ赤

基本は例の本Head First PHP & MySQL ―頭とからだで覚えるWebアプリケーション開発の基本からスタートしました。

1、検索フォーム側。

<form method=”get” action=”search.php“>
<label for=”usersearch”>フリーワード検索</label><br />
<input type=”text” id=”usersearch” name=”usersearch” /><br />
<input type=”submit” name=”submit” value=”検索” /><br />
</form>

一覧→詳細画面を作ったときの応用編でした。
method=”get” で、 actionに、検索結果画面のPHPを指定。
nameのパラメータで結果画面へ↓↓

2、検索結果画面で検索語を受け取る

$user_search = $_GET[‘usersearch’];

$_GETで、入力された検索WORDを受け取って$user_searchに入れる。

($user_searchの名前は何でもいい。)

3、検索初級編

$sql = “SELECT * FROM テーブル WHERE title_name LIKE%$user_search%‘”;

今までWHERE title_name = ‘$user_search'”;
のようにイコールで指定していたWHERE節、
イコールをLIKEに変えて、ワイルドガード%%で検索句を挟む。

こうするとtitle_nameのどこかに検索句が入っているものが引っかかる。

自分用の単純な一語の検索とかであればこれでも動く・・

(セキュリティ追記:SQLへの変数組み込みの前には、mysql_real_escape_stringを通すこと)

4、検索こだわり編
★google先生みたいに、スペースで区切って複数後で検索できるようにしたい。
(しかも全角半角スペース対応)
★コンマ区切りで複数ワードを入れられた場合も拾いたい。
→前述の本にも書いてあったのは、例えばコンマとかで句を区切られたらどうするか。
確かにこの業界にいる人はそんなことしないだろうけど、
何も考えずにコンマとかで区切る人はいるかもしれない。
コンマ含んで1語になったらそれはヒットしなくなってしまうので
そういうのも拾う対応。
★全角英数字やひらがなも拾いたい。
→私のデータベースはtitle_nameは全部カタカナor半角英数字。
基本的に全角英数字とひらがなは無い。
データベースにひらがなカラムとか全角カラム増やして全部登録するなんてやだ・・
ということでPHP側でなんとかしたい。
★半角カタカナも拾いたい。
→正直そんな人いないと思うしどうでもいいかとも思ったけど
世の中のパソコン初心者で半角の区別がつかない人のことをイメージして
ここまできたら思いつくものは全部やろうかと。

4-1 まず、ユーザーの検索後$user_searchの中の「、」を半角スペースに変換

$user_search = $_GET[‘usersearch’];

$not_words = array(“,”, “、”, “ ”, “。”, “.”);

$clean_search = str_replace($not_words, ‘ ‘, $user_search);

私の参照した本は翻訳本なので「,」の対応だけ書いてあったけど、
よく考えるといろいろな区切り文字があるので
上記のとおりのパターン(“,”, “、”, “ ”, “。”, “.”)を
str_replaceで半角スペースに変換しました。

4-2 半角カタカナの濁点はどうする?

最初は上の$not_wordsパターンに、半角濁点”゙”も入れていたのだけど、
濁点が半スペに変換されちゃうと
濁点なしの言葉になっちゃって正しくヒットしなくなってしまう・・

次の4-3で使用する「mb_convert_kana」で最後に半角⇔全角の変換対応をしようと
思ってたんだけど
まさにその関数のマニュアルにピピっときた書き込みが。
そうですね。変換の仕組みがないなら自分で作ればいいんだ!!
▼ということでその書き込みを自分用に改変したもの。
~~~~~~~~~~~~~~~~~~~~~~~~~~~
function han_kaku_to_jen_kaku($clean_search){
$replace_of = array(‘ヴ’,’ガ’,’ギ’,’グ’,
‘ゲ’,’ゴ’,’ザ’,’ジ’,
‘ズ’,’ゼ’,’ゾ’,’ダ’,
‘ヂ’,’ヅ’,’デ’,’ド’,
‘バ’,’ビ’,’ブ’,’ベ’,
‘ボ’,’パ’,’ピ’,’プ’,’ペ’,’ポ’);
$replace_by = array(‘ヴ’,’ガ’,’ギ’,’グ’,
‘ゲ’,’ゴ’,’ザ’,’ジ’,
‘ズ’,’ゼ’,’ゾ’,’ダ’,
‘ヂ’,’ヅ’,’デ’,’ド’,
‘バ’,’ビ’,’ブ’,’ベ’,
‘ボ’,’パ’,’ピ’,’プ’,’ペ’,’ポ’);
$_result = str_replace($replace_of, $replace_by, $clean_search);
return $_result;
}

$clean_search2 = han_kaku_to_jen_kaku($clean_search);
~~~~~~~~~~~~~~~~~~~~~~~~~~~

ということで、4-1で作ったコンマ等なしの$clean_searchから、
さらに半角カナの濁点
付だけを先に全角カナに変換して$clean_search2になりました。

4-3 全角英数字を半角に、ひらがなと半角カナを全角カナに変換する

ここで、前述もしました便利なmb_convert_kanaを使用。

$kana_search = mb_convert_kana($clean_search2, “aKCs”, “utf-8”);

“aKCs”というところで自分の好みにできます。
自分のデータベースの内容に合わせて設定しました。

a →「全角」英数字を「半角」に変換します。
K →「半角カタカナ」を「全角カタカナ」に変換します。
C →「全角ひらがな」を「全角カタカナ」に変換します。
s →「全角スペース」を「半角スペース」に変換します(U+3000 -> U+0020)。

そのほかの変換パターンはPHPマニュアルへ。

これで、4-2で作ったコンマ等の記号なし半角濁点なしの$clean_search2から、
さらに英数字が全て半角で、ひらがなや半角カナのない、私の求める$kana_searchを作りました。

4-4 念のため・・ユーザの入力語とがっちゃんこ。

$clean_search_mix = $clean_search . ” ” . $kana_search;

これは必要か分からないですが、
念のため変換前のユーザーの入力語も残そうと思って
4-1の$clean_searchと変換後の4-3の$kana_searchをがっちゃんこして、$clean_search_mixにしました。

4-5 半角スペースで各語が繋がっている状態を、バラバラに。

$search_words = explode(‘ ‘, $clean_search_mix);

explodeを使用して、半角スペース毎に$clean_search_mixを複数語に分断します。
これで複数の検索語が、$search_wordsに入っている状態。

4-6 仕上げ。半角スペースが連続になっていたらまずいので。

4-5で半角スペース毎に区切りましたが、
それまでの半角スペースへの変換で、半スペの連続ができてる可能性があります。
その状態だと4-5で「空」のワードが生まれているわけですね。
「空」で検索すると全てが引っかかってしまうので、
「空」のワードを除去。
そしてついにWHERE句を作る。
~~~~~~~~~~~~~~~~~~~~~~~~~~~
$final_search_words = array();
if (count($search_words) > 0) {
foreach ($search_words as $word) {
if (!empty($word)) {
$final_search_words[] = $word;
}
}
}

$where_list = array();
if (count($final_search_words) > 0) {
foreach ($final_search_words as $word) {
$where_list[] = “title_name LIKE%$word%‘”;
}
}

$where_clause = implode(‘ OR ‘, $where_list);
~~~~~~~~~~~~~~~~~~~~~~~~~~~
4-5の$search_wordsから、空でないものを
$final_search_wordsに入れて、それをWHERE区の部品に入れた
$where_list[]を生成。
最後にimplodeで、ORで繋げて一つの言葉した$where_clauseを作りました。
このあたりについては冒頭の本(Head First PHP & MySQL)を参照しました。

4-7 SQL文にいれる

$sql = “SELECT * FROM テーブル WHERE $where_clause“;

※入力値が空のときを考慮する場合。

$sql = “SELECT * FROM テーブル”;
if (!empty($where_clause)){
$sql .= “WHERE $where_clause“;

できた・・!!
フリーワード検索ということで、
すべてORでつないで
どれか引っかかるものは取り急ぎ全て出てくるようにしました。
これがANDの絞込みになるとまた違うとは思いますが、
大体の入力ワードは意図をくんで拾えるようになったかなーと思います^0^

☆☆2011/11/9 追記

SQLインジェクションについて。
SQL文は動的に組み立ててはいけないのでしょうか??
http://d.hatena.ne.jp/ajiyoshi/20100409/1270809525
調べ中。

☆☆2012/1/4 追記

SQLへの変数組み込みの前に必ず mysql_real_escape_string
HTMLへの変数書き出しの前に必ず htmlspecialchars

を対象変数に対してかける・・!

PHPで誰でも簡単Webサービス製作!でなんか作って公開した奴ちょっと来い - 甘味志向@はてな
タイトルは出来れば関連する方に読んで欲しかったので、軽く釣り針にしました。すみません。:*) 最近はやりのヒウィッヒヒー(Twitter)でも、よく「○○ったー」みたいなサービスがばんばん登場してますね! おかげでますますツイッターが面白い感じになってて、いい流れですね! でも・・・ちょっと気になることが・・・ 最近「...

—–

コメント

タイトルとURLをコピーしました