MT の検索結果をページ処理(Page Navigation)する方法 - Hack 編

MT の検索結果をページ処理(Page Navigation)する方法 - MTPaginate 編」で、Movable Type にページ処理機能を追加してくれる MTPaginate プラグインを導入することで検索結果にページ機能を実装する方法とその欠点をかきました。

今回は、それら欠点を解消する Movable Type Hack 編です。MT::ObjectDriver::DBI::mysql をオーバーライドして regexp 構文をサポートさせて、MySQL レベルでフィルタリングした検索結果を表示する MT::App::SearchPN クラスを作ることで検索結果にページ機能を実装する方法です。

- スポンサーリンク -

さて、導入方法について説明します。

  1. MT::App::SearchPN モジュールをインストールするスクリプトはこちら(SearchPN.pm) 

    上記リンクから MT::App::SearchPN モジュールをダウンロードします。ダウンロードしたファイルをそのまま Movable Type をインストールした先の /lib/MT/App/ ディレクトリに FTP してください。
    ※本モジュールは、MT3.1 以上に対応しています。その他のバージョンでは動作検証を行っておりません。
    ※本モジュールは、Database として MySQL を選択している場合にのみ動作するようになっています。その他の場合は通常の動作のままです。

  2. 検索結果 CGI (mt-search.cgil)を編集 MT::App::Search とかかれた部分を全て MT::App::SearchPN に修正してください。

  3. 検索結果ページのテンプレート(search_templates/default.tmpl)を編集 Movable Type の検索結果ページのテンプレートは、search_templates/default.tmpl になります。MT 3.2 でも検索結果ページのテンプレートは直接エディタによる編集でしか手がありません。日本語を扱うので、EUC や Unicode が扱えるエディタで編集して、素の文字コードのまま保存してください。

    以下のようにコードを追加下さい。(黒色の部分が素のコードで、赤色の部分が追加分です)

    <div style="text-align: center;">
    Results <b><$MTSearchResultsFirstIdx$></b> - <b><$MTSearchResultsLastIdx$></b> of <$MTSearchResultsTotal$>: <$MTSearchNavigation$>
    </div>

    <MTSearchResults> <MTBlogResultHeader>
    <h2><MT_TRANS phrase="Search Results from"> <$MTBlogName$></h2>
    </MTBlogResultHeader> <h3><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></h3>
    <p><$MTEntryExcerpt$> <$MTEntryEditLink$></p>
    <p class="posted"><MT_TRANS phrase="Posted in"> <$MTBlogName$> <MT_TRANS phrase="on"> <$MTEntryDate$></p> </MTSearchResults>

    以上で、ページナビゲーションが検索結果の上に表示されていると思います。下にも同じナビゲーションを表示したければ、

    <div style="text-align: center;">
    Results <b><$MTSearchResultsFirstIdx$></b> - <b><$MTSearchResultsLastIdx$></b> of <$MTSearchResultsTotal$>: <$MTSearchNavigation$>
    </div>
    と記述すれば良いだけです。検索結果ページに以下のようなナビゲーションが表示されるようになると思います。
    search.jpg

検索結果が0のときにページナビゲーションを表示したくない場合は、Movable Type の正規表現プラグインを導入して、

<MTIfNotMatches var="SearchResultsTotal" pattern="m/^0/">
<div style="text-align: center;">
Results <b><$MTSearchResultsFirstIdx$></b> - <b><$MTSearchResultsLastIdx$></b> of <$MTSearchResultsTotal$>: <$MTSearchNavigation$>
</div>
</MTIfNotMatches>

のように MTIfMatches, MTIfNotMatches タグを用いれば実現できます。エントリーのデータ数が少ない場合は、前回説明した方法と大差は無いと思いますが、エントリー数が 1000 とか超えている場合は体感できるくらいに速度が改善されていると思います。特に、mod_perl とか入れた場合に大きく処理速度の向上を感じることがデキルと思います。

その他制限等に関して

  • 実装方法がちょっとダサいかも・・・
    今回の実装は結構悩みまして、本当はプラグイン形式で配布したかったのですが、どうにも上手くいかず(特に import で MT::ObjectDriver::DBI::mysql とかをオーバーライドするあたりが・・・)モジュール追加での実装になってしまいました。元のモジュールを直接書き換えることは避けたかったので、SearchPN.pm という形をとることにしました。
  • エントリーのテキストおよび追記に対して検索を行います。コメント検索は実装していません。
    自分がコメント検索モードを一度も使ったことがないので、今回の実装から手抜きしています。entry_text, entry_text_more に対して、regexp 構文をかましています。
  • MySQL を使っている場合限定です。PostGreSQL 対応は非対応・・・
    検索条件を SQL に落とし込む際に like 構文ではなく、MySQL 独自の regexp 構文を用いているため PostGreSQL への移植は難しい?です。
  • 検索条件の入力は元の機能とほぼ同じ(と思う・・・)。
    regexp 構文を使っているので、元の MT の検索機能と同じ入力をでほぼ同じ結果を得ることができます。正規表現の入力周りはあまりチェックしていませんが、and, or, not 検索まわりはちゃんと動いていると思います。本当は、Senna + MySQL で日本語全文検索にしたかったのですが、導入の敷居が高くなるので見送りました。
- スポンサーリンク -