ちょっと意味不明なサブジェクトですが、どういうことかというと、今回 Movable Type で構築している案件で次のような仕様を実装することになりました。

  • 多数の加盟企業がそれぞれのユーザー名でログインしてそれぞれにお知らせを投稿する。
  • 加盟企業はそれぞれに自身の紹介ページが作られる。(紹介ページを作らない企業もあり)
  • 加盟企業の登録・編集は事務局が行う。(但し、事務局は Movable Type の管理者ではない)

制作を受ける際はできると考えていて、いざ構築を始めるとつまずくことがあるもので、今回の場合、Movable Type のユーザーにカスタムフィールドで企業情報を入力するフィールドを作って企業をユーザーとして登録し、企業の紹介ページはユーザー別アーカイブで生成っていうのが正当な方法なのでしょうが、これだと登録企業自身が情報を編集することが出来てしまいます。また、ユーザーの追加は Movable Type のシステム権限でないとできません。今回ユーザーを追加する事務局にはシステム権限を与えないので、別の方法を模索することになります。そこで、

  • あらかじめ想定される数のユーザーを user001,user002,user003,・・・というユーザー名で作っておく。
  • 加盟企業を登録するブログ(blog_id="2")を作り、登録の際にタグ欄にユーザー名を入力するようにする。
  • 加盟企業はそれぞれのユーザー名でログインし、お知らせのブログ(blog_id="3")に情報を掲載する。
  • お知らせを投稿したユーザー名と加盟企業のタグを関連づけ、お知らせ一覧に企業名と業種を、企業紹介ページにはその企業が投稿したお知らせを表示する。

という仕組みを考えました。しかし、テンプレートを書いていて問題が二つ発生しました。

まず、お知らせのブログのエントリー一覧の中で、別のブログである企業情報のエントリーを表示する、つまりトップページとなるウェブサイトのメイン・インデックスに表示する場合、<mt:Entries blog_ids="3"> の内側で <mt:Entries blog_ids="2"> を利用することになるのですが、<mt:MultiBlog> の入れ子が出来ないのと同じことなのでしょう、<mt:Entries> の入れ子の場合テンプレートエラーにはならないのですが、内側の <mt:Entries> は表示されませんでした。

そこで考えた方法が、まず <$mt:BlogEntryCount blog_ids="2"$> でリストアップするお知らせ件数を取得しておき、<mt:Entries blog_ids="2" offset="n" lastn="1"> で1件ずつお知らせを表示。
そのユーザー名から加盟企業一覧のブログで同じ値のタグを持つ企業名を取得して、<mt:Entries blog_ids="3" lastn="1" tag="(ユーザー名)"> で企業名と業種を表示。
これを、offset を1ずつ足しながら、取得したお知らせ件数分繰り返すという方法です。

具体的には以下のようになります。

<mt:Ignore><!-- (お知らせ件数を取得) --></mt:Ignore>
<mt:SetVarBlock name="count"><$mt:BlogEntryCount blog_ids="2"$></mt:SetVarBlock>
<mt:Ignore><!-- (トップページの場合は最大10件) --></mt:Ignore>
<mt:If name="body_id" eq="home">
	<mt:If name="count" gt="10"><mt:SetVar name="count" value="10"></mt:If>
</mt:If>
<mt:Ignore><!-- (offset の初期値を 0 に設定) --></mt:Ignore> <mt:SetVar name="offset" value="0">
<mt:Ignore><!-- (取得した件数分繰り返し) --></mt:Ignore> <mt:For var="i" from="1" to="$count">
<mt:If name="__first__"><dl></mt:If>
<mt:Ignore><!-- (お知らせを表示) --></mt:Ignore> <mt:Entries blog_ids="2" offset="$offset" lastn="1"> <dt><$mt:EntryDate format="%x"$></dt> <dd><a href="<$mt:EntryPermalink archive_type="Individual"$>"><$mt:EntryTitle encode_html="1"$></a></dd>
<mt:Ignore><!-- (ユーザー名を取得) --></mt:Ignore> <mt:SetVarBlock name="author"><$mt:EntryAuthorUsername$></mt:SetVarBlock> </mt:Entries>
<mt:Ignore><!-- (ユーザー名に一致するタグの企業情報を表示) --></mt:Ignore> <mt:Entries blog_ids="4" lastn="1" tag="$author"> <dd><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle encode_html="1"$></a> <span class="divide">|</span> <$mt:EntryCategory$></dd> </mt:Entries>
<mt:If name="__last__></dl></mt:If>
<mt:Ignore><!-- (offset に 1 を加算) --></mt:Ignore> <mt:SetVar name="offset" op="++">
</mt:For>

実際は業種ごとに異なるアイコンを表示するために業種カテゴリのフォルダ名を取得して class 属性に代入したり、お知らせタイトルや企業名からのリンクがパーマリンクではなく外部サイトである場合があったり、業種もメインカテゴリだけでなく複数のカテゴリが設定され、そのうえその他の業種には別フィールドの具体名を表示したり、さらにお知らせ一覧ページでは PageBute プラグインを使ってページ分割したりと、もっともっと複雑です。

次に、企業紹介ページにそれぞれの企業が投稿したお知らせの一覧を表示する方法。
上記の逆で、加盟企業を登録したブログのタグ名と一致するお知らせのブログのユーザー名を取得して、そのユーザーが投稿したお知らせ一覧を表示すればいいわけですが、この場合、企業紹介ページはブログ記事アーカイブです。つまり、MultiBlog を使ってもお知らせの更新時に再構築されません。

すぐに思いついたのが、サーバの cron を使って定期的に再構築を実行させる方法。しかし、今回のクライアント指定のサーバでは cron が使えませんでした。
そこで、お知らせのブログにユーザー別ブログ記事リストを作り、これを企業紹介ページに php インクルードで読み込むことにしました。

今回の場合、ユーザー別ブログ記事リストのパスを author/<$mt:AuthorName$>.php とします。
そして、企業紹介ページでこれを読み込む記述は以下のようになります。

<mt:SetVarBlock name="author"><mt:EntryTags><$mt:TagName$></mt:EntryTags></mt:SetVarBlock>
<mt:MultiBlog blog_ids="2"> <?php include("<$MTBlogSitePath$>author/<$mt:Var name="author"$>.php"); ?> </mt:MultiBlog>

特にたくさんのコンテンツがある案件ではなく、楽に構築出来る筈だったのですが、思いがけず頭を使うことになってしまいました。

(8月18日追記)
ユーザー名の入力を必須にするために、タグ欄ではなく、カスタムフィールドに置き換えました。
この場合、上記のソースコードの一部が以下のように変わります。

ユーザー名に一致するタグではなくカスタムフィールドの値の企業情報を表示するところ

<mt:Entries blog_ids="4" lastn="1" field:(customfieldbasename)="$author">

企業紹介ページでユーザー別ブログ記事リストを読み込む記述

<mt:SetVarBlock name="author"><mt:(CutomFieldName)></mt:SetVarBlock>