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."$')";
うん、スッキリ。これで意図したとおりのカテゴリー検索が行われるようになりました。