BLOG

【Movable Type】カテゴリ内で別のカテゴリで絞り込めるか検証してみた

Written by mizuno

INDEX

こんにちは、ミズノです。

ポータルサイトを実装する際、カテゴリとタグの両方を検索軸にしつつ、「カテゴリ+タグ」で絞り込めるようにしたいですよね。

Movable Typeにはタグ機能がありますが、「記事」や「ウェブページ」でのみ使用でき、カテゴリ一覧や年別一覧のように自動でページを生成する機能はありません。そのため、タグの一覧ページを作成するには、インデックステンプレートを使って手動で対応する必要があります。
また、カテゴリを複数設定することもできないため、今回の要件では「記事」を使用するのは難しそうです。

そのため、タグのページを持たせつつ「カテゴリ+タグ」で絞り込めるようにするには、Movable Type 7から追加された「コンテンツタイプ」を使用し、タグをカテゴリとして実装するのがよさそうです。

そこで今回は、犬の種類を掲載する架空のサイト「ワンコ図鑑」を実装しながら、検証してみたいと思います。
それでは、さっそく始めましょう!

※2025年2月時点、 Movable Typeバージョン8.4.1にて検証

1.完成イメージ

以下の内容で実装していきます。

  • 「サイズ」と「キーワード」のカテゴリを作成し、絞り込めるようにする
  • サイズは「大型・中型・小型」の3つに固定
  • キーワードは複数追加できる想定(タグ扱いなのでサブカテゴリは作成しない)
  • コンテンツタイプを使用する

以下は補足です。

コンテンツタイプと記事の違いとは

記事

記事は、コンテンツを時系列に並べて公開するのに適した形式です。公開された記事は、カテゴリや日付ごとにアーカイブされます。

コンテンツタイプ

コンテンツタイプは、Movable Type 7 から導入された新しいコンテンツ管理の形です。
記事のように蓄積されるものや、ウェブページのように個別に管理されるコンテンツのどちらにも対応できます。また、フィールドを自由に定義して利用することができます。

カテゴリセットと紐づけてHTMLファイルを生成することもできます。

引用:知識編:コンテンツタイプの仕組み

2.カテゴリセットの編集

管理画面のカテゴリセットの編集からカテゴリを追加していきます。
タグなのにカテゴリセット?と思うかもしれませんが、Wordpressのカスタムタクソノミーのように階層を持つか持たないかの違いなので、タグとして使用するカテゴリセットはサブカテゴリを持たない想定で運用してみます。

3.コンテンツタイプの編集

続いて、コンテンツタイプの編集から「ワンコ詳細」を追加し、情報を入力できるようにしました。
後々にテンプレートからコンテンツデータを絞り込む必要のある「サイズ」と「キーワード」はローマ字にしています。
※日本語や半角空白が含まれるコンテンツフィールドの場合は、field: の後ろに指定することはできませんのでユニーク ID を代わりに指定します。(参考: MTContents | Movable Type ドキュメントサイト

入力画面はこんな感じ。

9件ほど登録してみました。
これで下準備が完了したのでページ生成をしていきます。

4.テンプレート管理

テンプレートの管理から「コンテンツタイプリストアーカイブ」を選択します。

テンプレートの内容は一部抜粋して紹介します!
カレント表示とコンテンツデータを絞り込む用に変数を定義しておきます。

<!-- 変数定義 -->
<$MTCategoryLabel setvar='current_categorylabel'$>
<$MTCategoryBasename setvar='current_categorybasename'$>
<$MTCanonicalURL current_mapping="1" setvar='current_url'$>

<mt:If name='current_url' like='small'>
  <$MTSetVar name='size_category' value='small'$>
  <$MTSetVar name='size_category_label' value='小型犬'$>
<mt:ElseIf name='current_url' like='medium'>
  <$MTSetVar name='size_category' value='medium'$>
  <$MTSetVar name='size_category_label' value='中型犬'$>
<mt:ElseIf name='current_url' like='large'>
  <$MTSetVar name='size_category' value='large'$>
  <$MTSetVar name='size_category_label' value='大型犬'$>
</mt:If>

サイズ一覧表示。

<!-- サイズ一覧 -->
<mt:CategorySets content_type='ワンコ詳細' name='サイズ'>
  <mt:TopLevelCategories>
    <a href="<$MTWebsiteRelativeURL$>size/<mt:CategoryBasename>/" class="<mt:If tag='CategoryLabel' eq='$size_category_label'>is-current</mt:If>"><mt:CategoryLabel></a>
  </mt:TopLevelCategories>
</mt:CategorySets>

キーワード一覧表示。
サイズカテゴリとキーワードカテゴリでコンテンツデータを絞り込み、データが存在する場合にキーワードを表示するようにしています。

<!-- キーワード一覧 -->
<mt:CategorySets content_type='ワンコ詳細' name='キーワード'>
  <mt:TopLevelCategories>
    <mt:CategoryLabel setvar='keyword_name'>
    <mt:CategoryBaseName setvar='keyword_basename'>
    <mt:Contents field:size='$size_category_label' field:keyword='$keyword_name' limit='1'>
      <a href="<mt:If name='keyword_name' eq='$current_categorylabel'><$MTWebsiteRelativeURL$>size/<$mt:Var name='size_category'$>/<mt:Else><$MTWebsiteRelativeURL$>size/<$mt:Var name='size_category' lower_case='1'$>/<mt:CategoryBasename>/</mt:If>" <mt:If name='keyword_name' eq='$current_categorylabel'>is-current</mt:If>">#<mt:Var name='keyword_name'></mt:Var></a>
    </mt:Contents>
  </mt:TopLevelCategories>
</mt:CategorySets>

記事一覧表示。
サイズカテゴリ以外の場合は、コンテンツデータを絞り込みするようにしています。

<!-- 記事一覧 -->
<mt:If name='current_categorylabel' like='^(小型犬|中型犬|大型犬)'>
  <mt:Contents>
    <!-- ...省略 -->
  </mt:Contents>
<mt:Else>
  <mt:Contents field:size='$size_category_label' field:keyword='$current_categorylabel'>
    <!-- ...省略 -->
  </mt:Contents>
</mt:If>

5.アーカイブマッピング

「保存」を押し後にアーカイブマッピングの設定エリアが表示されるので、設定していきます。
サイズカテゴリはsize/〇〇/としたいので、以下のように設定してみました。

「変更を保存」した後に再構築をすると、サイズのカテゴリごとにhtmlが生成されていますね。

次に、サイズカテゴリの中にキーワードカテゴリのページを生成していきます。
下記の記事を参考にファイルの出力パスのカスタマイズをしました。

アーカイブマッピングにコンテンツフィールドの値を指定する方法
https://www.mt-hub.com/c/blogs/archive_mapping_include

アーカイブマッピング用にテンプレートモジュールを作成する

<mt:CategoryLabel setvar='keyword_name'>
<mt:CategoryBaseName setvar='keyword_basename'>
<mt:If name='size_category' eq='large'>
  <mt:Var name='category_set' value='大型犬'>
<mt:ElseIf eq='medium'>
  <mt:Var name='category_set' value='中型犬'>
<mt:ElseIf eq='small'>
  <mt:Var name='category_set' value='小型犬'>
</mt:If>
<mt:Contents content_type='ワンコ詳細' field:size='$category_set' field:keyword='$keyword_name' limit='1'>
  <mt:Var name='path' value='$keyword_basename'>
</mt:Contents>
<mt:If name='path'><mt:For regex_replace='/[\ \t\r\n]+/mg',''>size/<mt:Var name='size_category'>/<mt:Var name='path'>/index.html</mt:For></mt:If>

サイズカテゴリとキーワードカテゴリでコンテンツデータを絞り込み、データが存在する場合にパスを生成するようにしています。

マッピングのカスタマイズについて注意点があり、Movable Typeのテンプレートタグはアーカイブマッピングでも使用可能ですが、ブロックタグについては処理自体は行われるものの、正式にはサポートされていないようです。

以下、公式引用。

Q.アーカイブマッピングでテンプレートタグを使えますか
https://www.movabletype.jp/faq/can-use-templatetag-in-archivemapping.html

例えば、MTEntries、MTContents、MTIf が該当します。

アーカイブマッピングでは、これらのブロックタグも処理自体はおこないますが、正式なサポートはしておりません。使用制限は設けておりませんが、ブロックタグを使用したことで問題が発生した場合は、直ちにアーカイブマッピングでの使用を取りやめてください。

期待した出力結果が得られない場合は、直ちに別の方法で調整しましょう。

アーカイブマッピングにテンプレートモジュールを追加する

一覧のアーカイブテンプレートに戻りマッピングの設定を追加します。

「変更を保存」した後に再構築をすると、サイズのカテゴリごとにhtmlが生成されました。

6.完成

まとめ

今回の検証の結果、カテゴリと組み合わせての絞り込みには制約があることが分かりました。
タグのページを持たせつつ、カテゴリ+タグでの絞り込みを実現するには、カテゴリの中にサブカテゴリを作成し、タグと同じ内容を持たせる方法が確実のような気はします。(ただし、運用は複雑になります...)

引き続き、カスタムフィールドやプラグインの活用による別のアプローチも検討し、より効率的な実装方法を模索していきたいと思います。

参考文献