📃

【Movable Type】検索機能を実装する

2025/03/07に公開

概要

MTで検索機能(フォーム・結果表示)を実装する方法について解説しています。

本記事で紹介している内容以外にも、指定できる項目があります。以下公式マニュアルもご確認ください。

検索フォーム

検索フォームの記述例です。

<form method="get" id="search" action="<$mt:CGIPath$><$mt:SearchScript$>">
  <input type="hidden" name="IncludeBlogs" value="<$mt:BlogID$>">
  <input type="hidden" name="limit" value="<$mt:SearchMaxResults$>">
  <input type="hidden" name="blog_id" value="1">
  <input type="text" name="search" value="<$mt:SearchString$>">
  <button type="submit" name="button">検索</button>
</form>

フォームの送信先を指定する

検索の処理はmt-search.cgiで行われます。以下のようにスクリプトのURLを指定します。
MTCGIPathでMTのディレクトリURL、MTSearchScriptで検索スクリプト(初期ファイルはmt-search.cgi)を出力します。

<form method="get" id="search" action="<$mt:CGIPath$><$mt:SearchScript$>">
  <!-- フォーム部分 -->
</form>

フォームの送信方法はgetにしておきます。

検索対象のブログを指定する

以下の部分では、検索対象のブログ(ウェブサイト)を指定しています。
MTで管理しているすべてのブログを検索対象とする場合は、この記述をごそっと削除します。

<input type="hidden" name="IncludeBlogs" value="<$mt:BlogID$>">

複数のブログを検索対象とする場合、valueの値は直接IDを,(カンマ)で区切って指定します。以下のように変数を利用することも可能です。

<mt:SetVars>
  search_id=1,4
</mt:SetVars>

<form method="get" id="search" action="<$mt:CGIPath$><$mt:SearchScript$>">
  <input type="hidden" name="IncludeBlogs" value="<$mt:Var name='search_id'$>">
  <!--(略)-->
</form>

1ページに表示する検索結果の件数を指定する

以下の部分では、1ページに表示する検索結果の件数を指定しています。
この値は環境変数SearchMaxResultsで指定が可能です(初期値は20

<input type="hidden" name="limit" value="<$mt:SearchMaxResults$>">

検索結果の表示に利用するテンプレート(のブログID)を指定する

以下のように指定すると、指定したブログIDのシステムテンプレート「検索結果」を利用できます。以下の指定ではブログIDが1の検索結果テンプレートを利用します。
この記述をせず複数のブログIDを指定した場合は、name="IncludeBlogs"で一番はじめに指定したブログIDのテンプレートを利用します。

<input type="hidden" name="blog_id" value="1">

検索結果で表示される検索フォームに値をセットする

以下は入力フォーム部分です。value="<$mt:SearchString$>"は検索結果ページにおいて、フォームに入力した値がセットされます。

<input type="text" name="search" value="<$mt:SearchString$>">

検索結果表示

ウェブサイト(ブログ)の「システムテンプレート」にある「検索結果」テンプレートを利用します。また、検索結果のページはjsとMTMLを組み合わせて実装します。
検索結果のMTMLはすこし複雑なため、慣れないうちはMTのインストール済みテーマの「検索結果」テンプレートを必要に応じてカスタマイズして利用する方法がよいと思います。

構造

検索結果におけるMTMLのおおまかな構造は以下です。id="search-results-main"id="search-results" id="current-page"はjsで定義している部分です。

<!-- <head></head>内にjsを記述する(詳細は下記参照) -->

<div id="search-results-main">
  <mt:SetVarTemplate id="search_results" name="search_results">
    <mt:SearchResults>
      <!-- 検索がヒットした場合の処理 -->
      <mt:SearchResultsHeader>
        <div id="search-results">
          <span id="current-page" class="hidden"><$mt:CurrentPage$></span>
      </mt:SearchResultsHeader>

        <!-- 検索がヒットした時に表示する記事やウェブページの内容(ループ処理) -->

      <mt:SearchResultsFooter>
        </div>
        <mt:IfPreviousResults>
          <!-- ひとつ前の検索結果ページに関する処理 -->
        </mt:IfPreviousResults>
        <mt:IfMoreResults>
          <!-- 次の検索結果ページに関する処理 -->
        </mt:IfMoreResults>
      </mt:SearchResultsFooter>
    </mt:SearchResults>
  </mt:SetVarTemplate>

  <$mt:Var name="search_results"$>

  <mt:NoSearchResults>
    <!-- 検索が1件もヒットしなかった場合の処理 -->
  </mt:NoSearchResults>

  <mt:NoSearch>
    <!-- 検索フォームに何も入力せず検索ボタンを押した場合の処理 -->
  </mt:NoSearch>

  <!-- js部分(詳細は下記参照) -->
</div>

JavaScriptを記述する

検索結果表示において必要なjsを記述します。以下、<head></head>内に記述します。

<script>
  var user = <$mt:UserSessionState$>;
</script>

<script>
  <mt:IfMoreResults>
    function getResults(page) {
      //略
    }
    function swapContent(direction) {
      //略 
    }
  <mt:Else>
    <mt:IfPreviousResults>
      function swapContent(direction) {
        return true;
      }
    </mt:IfPreviousResults>
  </mt:IfMoreResults>
</script>

getResults()はAjax検索に利用される関数で、検索結果が2ページ以上ある場合に利用されます。MTNoSearchブロックの後ろにも、後述する記述箇所があります。
swapContent()はページ送り用の関数で、検索結果が1ページの場合と2ページ以上の場合で処理が変わります。

スクリプトの内容は、基本的にMTのインストール済みテーマの「検索結果」テンプレートのものをそのままコピペして利用します。以下公式マニュアルページにも記載されています(MTのバージョンにより記述内容が古い可能性があるので、テーマのテンプレートからコピペすることをオススメします)

また、以下を<body></body>内に記述します。上記公式マニュアルのサンプルコードでは、<mt:NoSearch></mt:NoSearch>のあとに記述があります。

<mt:IfMoreResults>
  <script>
    var div = document.getElementById('search-results');
    var results = {
      //略
    };
    var timer = window.setTimeout("getResults(" + <$mt:CurrentPage$> + ")", 1*1000);
  </script>
</mt:IfMoreResults>

MTSearchResultsの中身について

以下はMTSearchResultsの記述例です。MTSetVarTemplateを利用して変数(search_results)として定義しています。

<mt:SetVarTemplate id="search_results" name="search_results">
  <mt:SearchResults>
    <mt:SearchResultsHeader>
      <span id="current-page" class="hidden"><$mt:CurrentPage$></span>
      <mt:IfStatic><mt:IfStraightSearch><h2>「<$mt:SearchString$>」の検索結果 - <$mt:SearchResultCount$>件</h2></mt:IfStraightSearch></mt:IfStatic>
      <mt:IfTagSearch><h2>タグ「<$mt:SearchString$>」がついている記事 - <$mt:SearchResultCount$>件</h2></mt:IfTagSearch>
    </mt:SearchResultsHeader>

    <!-- 記事部分の処理 -->

    <mt:SearchResultsFooter>
      <nav>
        <ul>
      <mt:IfPreviousResults>
          <li><a href="<$mt:PreviousLink encode_html='1'$>" rel="prev" class="prev" onclick="return swapContent(-1);">« 前のページ »</a></li>
      </mt:IfPreviousResults>
      <mt:IfMoreResults>
          <li><a href="<$mt:NextLink encode_html='1'$>" rel="next" class="next" onclick="return swapContent();">« 次のページ »</a></li>
      </mt:IfMoreResults>
        </ul>
      </nav>
    </mt:SearchResultsFooter>
  </mt:SearchResults>
</mt:SetVarTemplate>
<$mt:Var name="search_results"$>

<!-- 記事部分の処理 -->には、出力する内容を記述します。MTEntries内で利用できるMTタグ(MTEntryTitleなど)が利用できます。
MTSearchResultsHeaderでは検索結果の見出しを、MTSearchResultsFooterではページネーションを出力しています。

MTNoSearchResultsの中身について

以下はMTNoSearchResultsの記述例です。

<mt:NoSearchResults>
  <mt:IfStatic><mt:IfStraightSearch><h2>「<$mt:SearchString$>」の検索結果</h2></mt:IfStraightSearch></mt:IfStatic>
  <mt:IfTagSearch><h2>タグ「<$mt:SearchString$>」がついている記事</h2></mt:IfTagSearch>
  <p>「<$mt:SearchString$>」と一致する結果は見つかりませんでした。</p>
</mt:NoSearchResults>

MTNoSearchの中身について

以下はMTNoSearchの記述例です。

<mt:NoSearch>
  <h2>検索について</h2>
  <p>すべての単語が順序に関係なく検索されます。フレーズで検索したいときは引用符で囲んでください。</p>
  <pre><code>"movable type"</code></pre>
  <p>AND、OR、NOTを入れることで論理検索を行うこともできます。</p>
  <pre><code>個人 OR 出版</code></pre>
  <pre><code>個人 NOT 出版</code></pre>
</mt:NoSearch>

とりあえず覚えておくといいMTタグ

検索結果を出力(処理)する際にとりあえず覚えておくといいMTタグです。

MTSearchResults

検索処理が実行されて結果が1件以上あった場合に出力(処理)されるブロックタグ。

MTSearchResultsHeader

ループ出力の一番はじめのときだけ実行されるブロックタグ。

MTSearchResultsFooter

ループ出力の一番最後のときだけ実行されるブロックタグ。

MTIfMoreResults

検索結果が2ページ以上ある場合に出力(処理)されるブロックタグ。

<mt:IfMoreResults>
  <li><a href="<$mt:NextLink encode_html='1'$>" rel="prev" class="prev" onclick="return swapContent();">« 次のページ »</a></li>
</mt:IfMoreResults>

MTIfMoreResults内で、次のページのURLを出力する。

MTIfPreviousResults

検索結果が2ページ以上ある、かつ現在表示されているページの前ページがある場合に出力(処理)されるブロックタグ。

<mt:IfPreviousResults>
  <li><a href="<$mt:PreviousLink encode_html='1'$>" rel="next" class="next" onclick="return swapContent(-1);">« 前のページ »</a></li>
</mt:IfPreviousResults>

MTIfPreviousResults内で、ひとつ前のページのURLを出力する。

MTNoSearchResults

検索処理が実行されて結果が1件もない場合に出力(処理)されるブロックタグ。

MTNoSearch

フォームに何も入力されないまま検索処理が実行された(mt-search.cgiに直接アクセスされた)場合に出力(処理)されるブロックタグ。
検索方法を記載しておくとよい。

MTCurrentPage

現在表示中の検索結果ページが全体の何ページ目かを数値で出力する。

MTIfStatic

テンプレートのステータスがスタティックで公開する設定になっている場合に実行される条件タグ。
検索結果では以下のようなMTMLで見出しの出力に利用されることが多い。

<mt:IfStatic><mt:IfStraightSearch><h2>「<$mt:SearchString$>」の検索結果 - <$mt:SearchResultCount$>件</h2></mt:IfStraightSearch></mt:IfStatic>

MTIfStraightSearch

実行した検索処理が、記事やウェブページを対象としたキーワード検索の場合に実行する条件タグ。

MTSearchString

検索時に入力した文字列(キーワード)を出力する。

MTSearchResultCount

検索結果に合致した結果の件数を数値で出力する。

MTIfTagSearch

実行した検索処理が、記事やウェブページに設定されたタグを対象とした検索の場合に実行される条件タグ。

MTで検索処理を実装する際の留意事項

MTでの検索にはmt-search.cgiを利用しますが、検索結果ではブラウザのアドレスバーにMTの管理画面ディレクトリのURLが表示されます。
イントラ環境で利用するぶんには利用者も限られているためさほど問題にはならないかと思いますが、コーポレートサイトなど一般に公開されるサイトでは、攻撃対象になりやすいなど、セキュリティに対する対策などリスクヘッジも鑑みて実装を検討する必要があります。

また、プログラムの処理が入るため、検索対象の記事数が多いとその分表示に時間がかかるというデメリットもあります。

以下はmt-search.cgiを使わずに検索機能を実装する案です。

検索システムを独自実装する

検索対象記事をJSON形式などで書き出し、PHPなどで検索システムを独自実装する方法です。作成するプログラムに対するセキュリティ対策や実装コストなどまた別の問題もありますが、柔軟に開発でき静的サイトにも組み込みやすいかと思います。

PowerCMSの場合はダイナミック検索機能を利用する

PowerCMSを利用している場合は、ダイナミック検索機能を実装できます。実装のためのMTMLはすこし複雑ですが、独自のページネーションも利用できmt-search.cgiと比べて処理が速いため、PowerCMSを利用しているのであれば、こちらをオススメします。
ダイナミック検索機能の詳細は、以下公式マニュアルをご確認ください。

外部の検索サービスを利用する

外部のサービスを利用するというのもひとつの手かと思います。月額や年額で費用はかかりますが、メンテナンスコストはある程度省けることと、サービスによっては柔軟なカスタマイズやアナリティクス解析などもできるため、長い目で見ると費用対効果は得られやすいかと思います。

一例ですが、MTの開発元であるシックス・アパート社は、「サイトサーチ」という検索サービスを提供しています(他にフォームサービスも提供しています)

https://movabletype.net/sitesearch/

公式リファレンスなど

主だったものを掲載しています。

Discussion