複数の検索語をハイライトしたいときの簡単なPHPのコード

IT系ニュース専用検索エンジンでは多くの検索エンジンと同じように、検索結果中の検索語を太字にして強調表示しています。複数のキーワードを指定されたとき、ちゃんとそれぞれ強調表示されるようにするにはちょっと工夫がいりました。

preg_replace("'($query)'i", "<strong>$1</strong>", $buf);

ベースになるのはこの正規表現。

function replace_search_result($query, $str)
{
    $query  = str_replace(' ', ' ', $query);
    $q = preg_split("'[\\s,]+'", $query, -1, PREG_SPLIT_NO_EMPTY);
    $qq = array();
    foreach ($q as $val) {
        $qq[] = "'(".preg_quote($val).")'i";
    }
    return preg_replace($qq, "<strong>$1</strong>", $str);
}

第1引数に検索語、第2引数に検索結果をそれぞれ文字列で与えて、強調表示された文字列を返します。

検索語に複数の単語を指定する際には全角スペース、半角スペース、カンマが使われることを想定しています。あらかじめstr_replaceで全角スペースを半角スペースに変換しているのはpreg_splitで文字化けないため。

mb_regex_encoding('UTF-8');
$q = mb_split("\\s| ", $query);

str_replaceとpreg_splitの行を上記のようにしても動きます。速度的にはほとんど変わらなかったので好みでしょう。

preg_replaceの第1引数に配列で渡していますが、これはforeachでpreg_replaceを呼び出すよりやや速いため。$qの値を正規表現の書式に直す処理はarray_mapやarray_walkでやるよりforeachで回した方が速かったです。

WordPressの検索語をハイライトするプラグインやPukiWikiのplugin/search.inc.phpも参考にしました。WordPressの方はHTMLの混じった文字列を置換するので少々複雑。PukiWikiは全角スペースでの区切りに未対応。

This entry was posted in いじる. Bookmark the permalink. Both comments and trackbacks are currently closed.

3 Comments

  1. RUF
    Posted 2009/11/12 at 11:59 am | Permalink

    このスクリプトを活用させていただいております。

    1つ質問なのですが、上記のようにHTMLタグ付けして置換する場合、強調表示対象文字列にアンカータグがもともと付くようになっていた場合、強調表示のタグがそのまま表示されたりするようになります。

    こうした場合はどうしたらよいでしょうか? もしよろしければご教示いただければと思います。

    どうぞよろしくお願い致します。

  2. RUF
    Posted 2009/11/12 at 1:37 pm | Permalink

    すみません。CakePHP1.2上でのことでした。自己解決しました。
    http://cakephp.jp/modules/newbb/viewtopic.php?topic_id=1547&forum=3&post_id=3543

    お騒がせ致しました。

  3. RJTA
    Posted 2013/01/05 at 12:18 pm | Permalink

    こちらのコードですが検索語に置換後のHTMLタグの文字が含まれていた場合
    HTMLタグ内の文字列も置換えてしまうので注意してください。

Page optimized by WP Minify WordPress Plugin