タグ検索を絞り込む(その2:カスタマイズ)

タグ検索を絞り込む(その2:カスタマイズ)

Posted at January 22,2009 1:55 AM
Tag:[Customize, MovableType, Search, Tag]

タグ検索を絞り込む(その1)」の続きで、Movable Type 4 でのカスタマイズ方法です。

1.タグの絞り込み検索の仕組み

タグ検索は CGI(mt-search.cgi)を実行します。実行したURLのクエリー文字列の「tag=」の部分に、検索するタグ名を与えることでタグ検索が行なわれます。

例えば、タグ「Movable Type」による初回のタグ検索は次のようなURLを実行します。

http://user-domain/mt/mt-search.cgi?blog_id=1&tag=MovableType&limit=20&IncludeBlogs=1

このクエリー文字列「tag=」の右辺に、「 AND (ANDの前後に半角スペース)」を与えれば、複数のタグによる検索が可能になります。

例えば、タグ「Movable Type」と「Customize」で検索を行なうには、次のURLを実行します。

http://user-domain/mt/mt-search.cgi?blog_id=1&tag=MovableType%20AND%20Customize&limit=20&IncludeBlogs=1

「 AND 」はいくらでも連結できます。検索文字列と「AND」の間の「%20」は、半角スペースをURLエンコードしたものです。

つまり、前回のタグ検索文字列と今回のタグ検索文字列を「 AND 」で連結するサブテンプレートを作れば、この絞り込み検索の仕組みが実現できる訳です。

2.カスタマイズ

このカスタマイズでは Split プラグインを事前にインストールしてください。

その後、2.1~2.3に該当するいずれかの設定を行なってください。該当しない場合は、それらしき部分に追加してください。

なお、デザインはすべて確認できておりませんので、不具合がありましたらご連絡ください。

2.1 4.2 以降の「既定のブログ」の場合

次のサブテンプレート(青色)を、テンプレートモジュールの「ブログ記事の概要」に追加してください。

<mt:If name="entry_archive">
    <mt:EntryIfTagged>
        <div class="entry-tags">
            <h4>タグ<span class="delimiter">:</span></h4>
            <ul>
                <li><mt:EntryTags glue='<span class="delimiter">,</span></li> <li>'><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;" rel="tag"><$mt:TagName$></a></mt:EntryTags></li>
            </ul>
<mt:searchString setvar="tag_name" />
<mt:if name="tag_name" like=" AND ">
  <mt:getVar name="tag_name" split=" AND " setvar="tag_list">
<mt:else>
  <mt:setVarBlock name="tag_list[0]"><mt:getVar name="tag_name"></mt:setVarBlock>
</mt:if>
 
<mt:setVar name="tag_data" value="" />
<mt:entryTags>
  <mt:setVar name="tag_flag" value="0" />
  <mt:loop name="tag_list">
    <mt:if tag="TagName" eq="$__value__">
      <mt:setVar name="tag_flag" value="1" />
    </mt:if>
  </mt:loop>
  <mt:unless name="tag_flag">
    <mt:setVarBlock name="tag_data" append="1"><a href="<mt:searchScript />?blog_id=<mt:blogID />&amp;tag=<mt:searchString>%20AND%20<mt:tagName />&amp;limit=20&amp;IncludeBlogs=<mt:blogID />" rel="tag" title="<mt:searchString />と<mt:tagName />のタグ一覧へ"><mt:tagName /></a>,</mt:setVarBlock>
  </mt:unless>
</mt:entryTags>
 
<h4>絞り込みタグ<span class="delimiter">:</span></h4>
<ul>
  <li><mt:getVar name="tag_data" regex_replace="/(.*),$/","$1" /></li>
</ul>
        </div>
    </mt:EntryIfTagged>
</mt:If>

2.2 4.0 ~ 4.1 の場合

次のサブテンプレート(青色)を、テンプレートモジュールの「タグ」に追加してください。

<MTEntryIfTagged>
<div class="entry-tags">
    <h4 class="entry-tags-header">タグ<span class="delimiter">:</span></h4>
    <ul class="entry-tags-list">
        <li class="entry-tag"><MTEntryTags glue='<span class="delimiter">,</span></li> <li class="entry-tag">'><a href="<$MTTagSearchLink$>&amp;IncludeBlogs=<$MTBlogID$>" rel="tag"><$MTTagName$></a></MTEntryTags></li>
    </ul>
<mt:searchString setvar="tag_name" />
<mt:if name="tag_name" like=" AND ">
  <mt:getVar name="tag_name" split=" AND " setvar="tag_list">
<mt:else>
  <mt:setVarBlock name="tag_list[0]"><mt:getVar name="tag_name"></mt:setVarBlock>
</mt:if>
 
<mt:setVar name="tag_data" value="" />
<mt:entryTags>
  <mt:setVar name="tag_flag" value="0" />
  <mt:loop name="tag_list">
    <mt:if tag="TagName" eq="$__value__">
      <mt:setVar name="tag_flag" value="1" />
    </mt:if>
  </mt:loop>
  <mt:unless name="tag_flag">
    <mt:setVarBlock name="tag_data" append="1"><a href="<mt:searchScript />?blog_id=<mt:blogID />&amp;tag=<mt:searchString>%20AND%20<mt:tagName />&amp;limit=20&amp;IncludeBlogs=<mt:blogID />" rel="tag" title="<mt:searchString />と<mt:tagName />のタグ一覧へ"><mt:tagName /></a>,</mt:setVarBlock>
  </mt:unless>
</mt:entryTags>
 
<h4 class="entry-tags-header">絞り込みタグ:<span class="delimiter">:</span></h4>
<ul class="entry-tags-list">
  <li class="entry-tag"><mt:getVar name="tag_data" regex_replace="/(.*),$/","$1" /></li>
</ul>
</div>
</MTEntryIfTagged>

2.3 小粋空間テンプレートの場合

次のサブテンプレート(青色)を、テンプレートモジュールの「タグ」に追加してください。

<mt:entryIfTagged>
<div class="entry-tags">
   <h3 class="entry-tags-header">タグ:</h3>
   <ul class="entry-tags-list">
   <mt:entryTags>
      <li class="entry-tag"><a href="<mt:tagSearchLink />&amp;IncludeBlogs=<mt:blogID />" rel="tag"><mt:tagName /></a></li>
   </mt:entryTags>
   </ul>
<mt:searchString setvar="tag_name" />
<mt:if name="tag_name" like=" AND ">
  <mt:getVar name="tag_name" split=" AND " setvar="tag_list">
<mt:else>
  <mt:setVarBlock name="tag_list[0]"><mt:getVar name="tag_name"></mt:setVarBlock>
</mt:if>
 
<mt:setVar name="tag_data" value="" />
<mt:entryTags>
  <mt:setVar name="tag_flag" value="0" />
  <mt:loop name="tag_list">
    <mt:if tag="TagName" eq="$__value__">
      <mt:setVar name="tag_flag" value="1" />
    </mt:if>
  </mt:loop>
  <mt:unless name="tag_flag">
    <mt:setVarBlock name="tag_data" append="1"><a href="<mt:searchScript />?blog_id=<mt:blogID />&amp;tag=<mt:searchString>%20AND%20<mt:tagName />&amp;limit=20&amp;IncludeBlogs=<mt:blogID />" rel="tag" title="<mt:searchString />と<mt:tagName />のタグ一覧へ"><mt:tagName /></a>,</mt:setVarBlock>
  </mt:unless>
</mt:entryTags>
 
<h3 class="entry-tags-header">絞り込みタグ:<span class="delimiter">:</span></h3>
<ul class="entry-tags-list">
  <li class="entry-tag"><mt:getVar name="tag_data" regex_replace="/(.*),$/","$1" /></li>
</ul>
</div>
</mt:entryIfTagged>

3.サブテンプレート解説

2項のサブテンプレートの機能は、検索結果に表示されているブログ記事のタグから、現在の検索結果ページの検索タグを除外して表示します。そして、CGI(mt-search.cgi)のURLに、今回までの検索タグを「tag=」のクエリーに与えます。

このサブテンプレートを、いくつかのブロックに分けて解説します。

3.1 検索タグを分割して配列変数に設定

<mt:searchString setvar="tag_name" />
<mt:if name="tag_name" like=" AND ">
  <mt:getVar name="tag_name" split=" AND " setvar="tag_list">
<mt:else>
  <mt:setVarBlock name="tag_list[0]"><mt:getVar name="tag_name"></mt:setVarBlock>
</mt:if>

最初の MTSearchString タグで、今回表示されているタグ検索結果を変数 tag_name に保存します。変数 tag_name に「 AND 」が含まれていたら、split モディファイアを利用して、配列変数tag_listに、これまでのすべての検索タグを保存します。「 AND 」が含まれていない場合は、後続の処理で MTLoop タグを利用できるように、配列変数 tag_list の先頭に入れなおします。

3.2 ブログ記事に含まれるタグ一覧から、配列変数に設定されたタグを除外

<mt:setVar name="tag_data" value="" />
<mt:entryTags>
  <mt:setVar name="tag_flag" value="0" />
  <mt:loop name="tag_list">
    <mt:if tag="TagName" eq="$__value__">
      <mt:setVar name="tag_flag" value="1" />
    </mt:if>
  </mt:loop>
  <mt:unless name="tag_flag">
 ...中略...
  </mt:unless>
</mt:entryTags>

変数 tag_data を初期化し、MTEntryTag タグで、タグ検索でヒットしたブログ記事に含まれる、タグの一覧を処理します。変数 tag_flag は、これまでに使われた検索タグを出力から除外するためのフラグです。

フラグを設定する処理は、MTLoop タグを使って配列変数 tag_list をサーチすることで実現しており、これまでに使われた検索タグをみつけたら、変数 flag に 1 を設定します。

変数 tag_flag に 1 が設定されたら、次の MTUnless タグブロック内は実行せず、まだ検索タグとして登場していないタグだけを MTUnless タグブロック内で出力します。

3.3 ブログ記事に含まれるタグ一覧を変数に設定

<mt:unless name="tag_flag">
  <mt:setVarBlock name="tag_data" append="1"><a href="<mt:searchScript />?blog_id=<mt:blogID />&amp;tag=<mt:searchString>%20AND%20<mt:tagName />&amp;limit=20&amp;IncludeBlogs=<mt:blogID />" rel="tag" title="<mt:searchString />と<mt:tagName />のタグ一覧へ"><mt:tagName /></a>,</mt:setVarBlock>
</mt:unless>

MTUnless タグ内部では、タグ検索用のリンクを出力します。href 属性の値に、前回までの検索タグを MTSearchString タグ、そして今回の検索タグを MTTagNameタグ で与え、その間を「%20AND%20」で区切ります。リンクは直接出力せず、MTSetVarBlock タグを使って、変数 tag_data に一旦保存します。理由はあとで説明します。

3.4 ブログ記事に含まれるタグ一覧を出力

絞り込みタグ:<mt:getVar name="tag_data" regex_replace="/(.*),$/","$1" />

すべての処理が終わったら、変数 tag_data を出力します。

出力するタグの区切り文字をカンマ「,」にしているのですが、一番最後の「,」を、MTUnless タグブロック内の処理で出力しない制御がかなり面倒(=出力するタグが繰り返しの最後であることを判定するのが面倒)だったので、出力結果を一旦変数に保持し、変数を出力するときに regex_replace モディファイアで最後の1文字、つまりカンマを除去しています。

今回のタグ検索で使ったタグは、次のタグ検索結果ページの MTSearchString タグで取得できるので、再帰的な検索が行なえます。

関連記事
トラックバックURL


トラックバック

[MT]タグ検索結果を絞り込み!複数タグでAND検索(1) from Notebook :: Hibi no Note
Movable Typeのカスタマイズ ネタです。 このブログのタグ検索画面で表示されるタグのリンクを表示するように変更しました。また、リンクをクリックす... [続きを読む]

Tracked on June 1, 2009 4:21 PM
コメント

こんばんわ^^

やっぱりそうでしたか (●´∀`●)
ブログ検索では AND 検索可能なので同じ mt-search.cgi ならタグ検索も・・・と考えてました。

じゃぁ、わたし検索されたエントリのタグクラウドを作ってみよっかなぁ。
そこから絞込みを可能にしてみます。

[1] Posted by bzbell logo : January 22, 2009 10:10 PM

>bzbellさん
こんばんは。
それでは楽しみにお待ちしています。
タグネタ、まだまだ色々ありそうですね。
ではでは!

[2] Posted by yujiro logo : January 23, 2009 1:38 AM

さっそく参考にさせて頂きました。
タグクラウドでサイドバーに表示したかったのですが、クラウドにする為にはもう一工夫必要なようです。

[3] Posted by footbrain.pip.verisignlabs.com logo : January 31, 2009 8:09 PM

こんばんは。
パーフェクトガイド4.2のテンプレートでは、テンプレート「メタデータ」に挿入するのだと思いますが、8行目の次に挿入したところ、最初から、絞込みTagが表示されてしまいます。おそらく、Tag検索をして、はじめて絞込みTagが表示されると思うのですが、挿入場所が違うのでしょうか、それとも、他に手を加えるところがあるのでしょうか。
宜しく、お願いいたします。

[4] Posted by nero : March 6, 2009 12:09 AM

>neroさん
こんばんは。
ご質問の件ですが、説明に不足がありました。
「メタデータ」に設定した状態で、追加した青色のサブテンプレートを、下記のテンプレートタグで括ってみてください。

<mt:if name="search_results">
    :
   中略
    :
</mt:if>

それではよろしくお願い致します。

[5] Posted by yujiro logo : March 6, 2009 12:46 AM

こんばんは。

そのようにしてみたら、表示は正常になったのですが、Tagによっては下記のエラーがでるようになってしまいました。上記のテンプレートタグで括る前は表示はおかしかったものの、エラーはでなかったのですが。

テンプレート「検索結果」の再構築中にエラーが発生しました: <mtgetVar>タグでエラーがありました: 
<mtsearchResults>タグでエラーがありました:
<mtinclude>タグでエラーがありました: 
error in module ブログ記事の概要: 
テンプレート「ブログ記事の概要」の再構築中にエラーが発生しました: <mtinclude>タグでエラーがありました: 
error in module メタデータ: 
テンプレート「メタデータ」の再構築中にエラーが発生しました: 
<mtif>タグでエラーがありました: 
<mtentryIfTagged>タグでエラーがありました: 
<mtif>タグでエラーがありました: 
<mtsearchResults>タグでエラーがありました: 
<mtinclude>タグでエラーがありました: 
モジュールでお互いがお互いを参照している状態になっています: 
ブログ記事の概要

宜しくお願いします。

[6] Posted by nero : March 6, 2009 9:43 PM

>neroさん
こんばんは。
ご返事遅くなってすいません。
[5]の回答は誤りでした。申し訳ありません。

<mt:if tag="searchString">
    :
   中略
    :
</mt:if>

としてください。
それではよろしくお願い致します。

[7] Posted by yujiro logo : March 16, 2009 12:34 AM

こんばんは。

無事、正常に表示することができました。
ありがとうございます。

ちょっと、諦めかけていたので、助かりました(^^)

[8] Posted by nero : March 22, 2009 8:41 PM
コメントする
greeting

*必須

*必須(非表示)


ご質問のコメントの回答については、内容あるいは多忙の場合、1週間以上かかる場合があります。また、すべてのご質問にはお答えできない可能性があります。予めご了承ください。

太字イタリックアンダーラインハイパーリンク引用
[サインインしない場合はここにCAPTCHAを表示します]

コメント投稿後にScript Errorや500エラーが表示された場合は、すぐに再送信せず、ブラウザの「戻る」ボタンで一旦エントリーのページに戻り(プレビュー画面で投稿した場合は、投稿内容をマウスコピーしてからエントリーのページに戻り)、ブラウザをリロードして投稿コメントが反映されていることを確認してください。

コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。例えば「<$MTBlogURL$>」は「&lt;$MTBlogURL$&gt;」となります(全て半角文字)