| @技術/プログラミング

 P_BLOGのカテゴリー検索(category.php)は部分一致検索気味で、例えば"昔の日記"というカテゴリーと"日記"というカテゴリーがあったとするなら、日記のカテゴリーを選択したときに前者まで含まれてしまうのですよね(やっぱりうまくいかないカテゴリー検索)。そういうわけで、後方一致がおきないようにカテゴリー(TAG)をつけるようにしていたのですが、うっかり後方が重複するカテゴリーができてました。"本"と"熊本"です。地名は盲点だった :-!

 しょうがないのでもう一度 category.php いじりにチャレンジしてみました。


//=====================================
// CATEGORY LIST UP QUERY -- HOW?
//=====================================

$patterns = '/(*|+|^|$|?|(|))/';
if (preg_match($patterns, $key)) {
    // (1) Use "LIKE" search
    $listup_query = "BINARY category LIKE '%".$key."%')";
} else {
    // (2) Use MySQL Regular Expression
    $listup_query = "category REGEXP BINARY '^".$key."$|^".$key.",|,".$key.",|,".$key."$|,?".$key.",|,?".$key."$')";
}

 前回取り組んだとき(世間は連休なのに引きこもってブログで遊んでても(・∀・)イイ!)よりかは少しだけPHPのことが分かるようになったので、このコードが何をしようとしているのかくらいは理解できました。もし選択されたカテゴリー名($key)がパターン($patterns)にマッチしたら "LIKE" 検索を行い、そうでなければ MySQL の正規表現検索を行うということですね。

 ということは、カテゴリー名に $patterns で指定されているもの(検索演算子かな?)を含まないときは常に (2) の MySQL 正規表現検索が行われるのだから、こちらの方に手を加えればいいということが分かりました。おぉ、前回やったときよりも随分論理的に物事が進んでいる :-)

 それではまず正規表現について勉強しようと、Wikipedia で正規表現について調べてみました。

量化

文字やグループの後ろの量化子は、直前の表現が何回現れることが許されるかを指定する。非常によく使われる量化子は ? と * と + である。

?
疑問符は直前の表現が0個か1個あることを示す。例えば、"colou?r" は color と colour にマッチする。
*
アスタリスクは直前の表現が0個以上あることを示す。例えば、"go*gle" は ggle、gogle、googleなどにマッチする。

(中略)

^ 行の最初にマッチする。

$ 行の最後にマッチする。

 なるほど、$listup_query = "category REGEXP BINARY '^".$key."$|^".$key.",|,".$key.",|,".$key."$|,?".$key.",|,?".$key."$')"; でそれぞれの $key の前後についている記号にはいろいろ意味があるんですな。P_BLOG では複数のカテゴリーを登録する場合、区切りにコンマ(,)が追加されるのですが、例えば ,?".$key.", という書き方だと、$key(キーワード)の前に何か別の一文字があっても条件に一致することになります。まさに "熊本" が "本" のカテゴリーに含まれるということなんですよ。

 そういうわけなので、"?" を含むものを $listup_query から除外し、以下のように記述しました。


    $listup_query = "category REGEXP BINARY '^".$key."$|^".$key.",|,".$key.",|,".$key."$')";

 うん、スッキリ。これで意図したとおりのカテゴリー検索が行われるようになりました。