Ajaxによるモジュール化(jQuery版)
Movable Type 5のサイドバーの各リストを、Ajaxによるモジュール化を行う方法を紹介します。

このエントリーは3年ほど前に書いた「Ajax によるモジュール化」をjQuery向けに書き直したものです。
1.jQueryのダウンロード
jQuery(jquery.min.js)はjQueryの公式サイトから最新版をダウンロードしてサイトパスにアップロードするか、Movable Typeに同梱されている、mt-static/jquery/jquery.min.jsをそのまま利用します。
script要素の設定については5項を参照してください。
2.インデックステンプレートの作成
サイドバーに表示するリスト類はウィジェットに登録されているものを利用していると思いますが、Ajax化するにはこれらをインデックステンプレートに登録し直します。
例えば、「最近のブログ記事」をAjaxで表示させたい場合、「デザイン」→「テンプレート」→「インデックステンプレートの作成」をクリックし、ウィジェットにある「最近のブログ記事」をテンプレートの内容にコピーします。他の項目には下記を設定します。
- テンプレート名:最近のブログ記事
- 出力ファイル名:recentEntries.html
- テンプレートの種類:カスタムインデックステンプレート
- ファイルへのリンク:(設定不要)
- 公開:スタティック

複数のリストをAjax化するには、同じ作業を繰り返します。
3.テンプレートの修正
インデックステンプレートやアーカイブテンプレートに、2項で作成した「最近のブログ記事」を表示させるには、「サイドバー」テンプレートモジュールに次の内容を設定します。
<div id="entries"></div>
<script type="text/javascript">
//<![CDATA[
getFile('<mt:BlogURL />recentEntries.html', 'entries');
//]]>
</script>
1行目のdiv要素の内容に「最近のブログ記事」を表示します。その後にあるJavaScriptがdiv要素に「最近のブログ記事」を表示するためのスクリプトです。
getFile()のパラメータには、Ajaxで取得したいファイル名(ここでは2項で設定した「出力ファイル名」)と、リストを表示させるdiv要素のid 属性値(ここでは「entries」)を設定します。
「サイドバー」への設定イメージは次のようになります。

さらに他のリストを表示させるには、上記と同じセットを追加し、div要素のid属性値とgetFile()のパラメータを書き換えます。
4.JavaScript の追加
下記のスクリプトを外部ファイル(ajaxUtil.js)として保存し、サイトパスにアップロードします。
function getFile(url, id) {
jQuery.ajaxSetup({
cache: false
});
jQuery('#'+id).load(url);
}
getFile()の中で、jQueryのload関数を呼び出しています。また、キャッシュを無効にするため、ajaxSetupを利用しています。
リストが増えてもこのファイルを追加・変更する必要はありません。
5.script 要素の追加
jquery.min.jsと4項のスクリプトを読み込むため、「HTMLヘッダー」テンプレートモジュールに以下の内容を追加します。
<script type="text/javascript" src="<mt:StaticWebPath />jquery/jquery.min.js"></script>
<script type="text/javascript" src="<mt:BlogURL />ajaxUtil.js"></script>
「HTMLヘッダー」への設定イメージは次のようになります。
上のコードは、MTに同梱されているjquery.min.jsを利用した場合です。独自にダウンロードしたjquery.min.js(ブログのサイトパスにアップロード)を利用する場合は次のようにしてください。
<script type="text/javascript" src="<mt:BlogURL />jquery/jquery.min.js"></script>
<script type="text/javascript" src="<mt:BlogURL />ajaxUtil.js"></script>
Movable Type 4 の PHP モジュール化
インデックステンプレートを用いて、「最近のブログ記事」や「カテゴリーリスト」などのサイドバーのリスト類について、SSI(PHP)によるモジュール化を行なう方法を紹介します。
このエントリーは、Movable Type 3 の記事「Movable Type の PHP モジュール化の仕組みについて(その3:変更方法)」を Movable Type 4 向けに全面的に書き直したものです。Movable Type 4 では、サイドバーのリスト類がテンプレートからウィジェットに移動されているので、その辺りも考慮した内容にしています。
モジュール化のメリットについては、下記のエントリーを参照してください。
なお、各ページは事前に PHP 化を行っていることを前提としています。PHP化の方法については下記の記事を参照願います。
1.ウィジェットテンプレートの変更
Movable Type 4 では、サイドバーのリスト類はウィジェットに登録されているので、まずウィジェットテンプレートを変更します。以下、「最近のブログ記事」の場合を例に説明します。
ブログ管理画面の「デザイン」→「ウィジェット」をクリック。

「最近のブログ記事」をクリック。

テンプレートの内容を全選択してコピーします。コピーした内容はメモ帳などにペーストしておいてください。

テンプレートの内容を次の内容に書き換えます。
<?php readfile("<$mt:BlogSitePath$>recent_entries.html"); ?>
青色の部分がモジュールとして呼び出すファイル名になります。ファイル名は何でもかまいませんが、ここでは recent_entries.html で作業を進めます。
書き換えた後の画面は次のようになります。

書き換えたら「保存」をクリックします。
2.モジュールの作成
次に、モジュールとなる方のテンプレートを作成します。
ブログ管理画面の「デザイン」→「テンプレート」をクリック。

インデックステンプレートの「新しいインデックス・テンプレートを作る」をクリック。

インデックステンプレート作成画面で下記の項目を設定します。
- テンプレートの名前:最近のブログ記事
- 出力ファイル名:recent_entries.html
- テンプレートの内容:1項の作業でウィジェットからコピーテンプレートの内容をペースト
「出力ファイル名」は、このテンプレートを再構築した時のファイル名となります。このファイル名は、1項で設定した青色部分、
<?php readfile("<$mt:BlogSitePath$>recent_entries.html"); ?>
と必ず一致するようにしてください。
各項目を設定した後の画面は次のようになります。

あとは「保存」をクリックして、「このテンプレートを再構築する」のリンクをクリックし、作成したテンプレートを再構築してください。

あとは、全体を再構築して、リストが正常に表示されることを確認してください。
3.「最近のブログ記事」以外のリストをモジュールで利用する場合
モジュール化したいリストについて、1~2項の手順を繰り返します。その際、出力するファイル名を次のように変更してください。
- 最近のコメント:recent_comments.html
- 最近のコメント:recent_trackbacks.html
- カテゴリーリスト:categories.html
- 月別アーカイブリスト:monthly.html
必ずこの名称にしないといけないわけではなく、1項で設定した青色部分のファイル名と、2項で設定した出力ファイル名が一致していればOKです。
また、リスト類以外の検索フォームなど、テンプレートタグを使っているものについても、モジュール化しておけば再構築の負荷を減らすことができます。
4.システムテンプレートでもモジュールを利用する場合
「コメントプレビュー」や「検索結果」などのシステムテンプレートから、作成したモジュールを呼び出すときは、「最近のブログ記事」の場合、1項のウィジェットの内容を次のように修正します。
<mt:If name="system_template">
<$mt:Include file="recent_entries.html"$>
<mt:Else>
<?php readfile("<$mt:BlogSitePath$>recent_entries.html"); ?>
</mt:If>
青色部分のファイル名が一致するようにしてください。
以上です。
MTInclude タグによる SSI(サーバサイドインクルード)不要なインデックステンプレートのモジュール化
MTInclude タグによるインデックステンプレートのモジュール化を紹介します。
注:この手法は再構築を行わないと情報が更新されないので、比較的静的な情報か、定期的に再構築を行う運用環境でご利用ください。
1.概要
「最近のブログ記事」をモジュール化する例で、イメージ図を示します。

サイドバーに表示する「最近のブログ記事」をモジュール化する場合、インデックステンプレートで作成します。ファイル名は recent_entry.html としておきます。
次にメインページやブログ記事などのテンプレートに MTInclude タグを記述して、file モディファイアに recent_entry.html を指定します。file モディファイアで指定したファイルの内容は、出力するページ内に展開されます。
この方法を用いれば、すべてのページに対し、同じ内容の「最近のブログ記事」を表示することができます。
「最近のブログ記事」以外に、「最近のコメント」「最近のトラックバック」「カテゴリーリスト」「月別アーカイブリスト」「タグクラウド」などにも適用できます。
2.メリット・デメリット
メリット
- リストの再構築回数を減らせるので、全体の再構築時間の短縮が可能です。
- 全ページで同じ内容のリストを表示することができます。
- SSI(サーバサイドインクルード)の設定が不要。PHP化も不要です。
デメリット
- リストの表示内容を更新するには、再構築が必要です。
3.具体的なカスタマイズ例
Movable Type 4 以降で、デフォルトテンプレートの「ウィジェット」にある「最近のブログ記事」をモジュール化してみます。配布テンプレートでも同じ作業です。
ブログ管理画面の「デザイン」→「テンプレート」の「インデックステンプレートを作成」をクリック。

インデックステンプレート作成画面で次の内容を設定。
テンプレート名:最近のブログ記事
テンプレートの内容:「ウィジェット」の「最近のブログ記事」の内容をそのままペースト
出力ファイル名:recent_entry.html(拡張子は .html でなくても構いません)
テンプレートの種類:カスタムインデックステンプレート
公開:スタティック

作成したら保存し、再構築まで行ってください。再構築後、テンプレート編集画面右の「公開されたテンプレートを確認」をクリックして、ファイルが出力されたことを確認してください。次のような、スタイルを適用していないテキストが表示されていればOKです。

ブログ管理画面の「デザイン」→「ウィジェット」→「最近のブログ記事」を開き、テンプレートの内容を削除して、次のサブテンプレートを設定。
<$MTBlogSitePath cat="recent_entry.html" setvar="recent_entries"$>
<$MTInclude file="$recent_entries"$>
サブテンプレート設定後は次のようになります。

解説すると、MTBlogSitePath タグはURLではなく、ブログディレクトリまでのパスを出力します。cat モディファイアに先ほど作成したインデックステンプレートで出力するファイル名 recent_entry.html を設定することで、ブログディレクトリのパスにファイル名を結合した形で出力します。
そして setvar モディファイアで、出力する内容を変数 recent_entries に設定します。
MTBlogSitePath タグに設定した2つのモディファイアの順番は逆転させないでください。グローバルモディファイアは先に設定したものから順番に処理を実行します。もし、順序を逆転させると、変数 recent_entries には recent_entry.html が設定されません。
グローバルモディファイアの順序性については、「Movable Type 4.2 パーフェクトガイド」をお持ちであれば、類似した事例が425 ページの下から3段目のパラグラフにあります。参考になれば幸いです。
MTInclude タグの file モディファイアには、設定した変数 recent_entries を指定します。変数の先頭に「$」をつけるのを忘れないでください。
ここでは file モディファイアに変数を設定しましたが、次のように recent_entry.html までのパスを直接指定してもかまいません。
<$MTInclude file="/home/hoge/www/recent_entry.html"$>
設定したら保存して、メインページなどの各テンプレートを再構築して、表示を確認してください。

4.デフォルトテンプレートで「最近のブログ記事」などをすべてのページに表示する
デフォルトテンプレートでは「最近のブログ記事」「最近のコメント」などのいくつかのウィジェットは「ホームページウィジェットグループ」ウィジェットを経由してインクルードしているので、上記の設定だけではメインページだけしか表示されません。
すべてのページでウィジェットを表示させるには、「ホームページウィジェットグループ」ウィジェットにある MTIf タグを削除するか、囲む位置を変更します。
例えば、「最近のブログ記事」だけを全ページに表示させるには次のように変更します。
変更前
...前略...
<mt:If name="main_index">
<$mt:Include widget="最近のコメント"$>
<$mt:Include widget="最近のブログ記事"$>
<$mt:Include widget="アイテム"$>
<$mt:Include widget="タグクラウド"$>
</mt:If>
変更後
...前略...
<mt:If name="main_index">
<$mt:Include widget="最近のコメント"$>
</mt:If>
<$mt:Include widget="最近のブログ記事"$>
<mt:If name="main_index">
<$mt:Include widget="アイテム"$>
<$mt:Include widget="タグクラウド"$>
</mt:If>
5.トラブルシューティング
MTInclude タグを利用するので、目的のファイルがみつからない場合、再構築でエラーが発生します。

エラーが発生した場合、次のような原因がないか、確認しましょう。
- インデックステンプレートで作成したファイルの実体が存在しない(未再構築)。
- MTInclude タグで指定したファイル名が誤っている。
- MTInclude タグで指定したファイルのパスが誤っている。
Ajax によるモジュール化
Movable Type のサイドバーの各リストを、Ajax でモジュール化を行う方法を紹介します。
1.PHP モジュール化と Ajax モジュール化の違い
Movable Type における PHP モジュール化には次のようなメリットがあります。
- 再構築時間の削減
- アーカイブに依存しないリストの生成(今回はここに言及しません)
ただし PHP モジュール化は、ユーザがブラウザからインクルード元のページにアクセスした時、インクルード元のページはインクルード先の各モジュールを読み込んだコンテンツを生成・返却するため、サイドバーに多くの情報をインクルードしていると、PHP でページを生成する分、表示が遅延します。
本題とはそれますが、WordPress で表示までに若干のタイムラグが生じるのは、この PHP によるページ生成が行われるためです(キャッシュや条件付きGETが機能していればこの限りではありません)。
Ajax モジュール化を利用すれば、サイドバーの情報は非同期で表示させられるので、ユーザはページをストレスなく閲覧することが可能になります。
再構築時間は PHPモジュール化と同じ効果があります。
ただし内部リンク等がインクルード元のページに表れないため、SEO という観点では注意が必要かもしれません。
当サイトでは、数ヶ月前からサイドバーやメインページ上部にある多くのリストを Ajax モジュール化しており、安定して表示されることが確認できたので、本エントリーにて設定方法を説明します。
また、Ajax と JavaScript の併用や関連テクニックについても分かる範囲で解説しています。
以下、当サイトの配布テンプレートをサンプルに、「最近のエントリー」の Ajax モジュール化を例にします。
2.prototype.js のダウンロード・アップロード
上記のサイトにある Download the latest version のリンクをクリックし、アーカイブをダウンロードします。アーカイブを解凍して、dist フォルダの中にある prototype.js を使用します(他は使いません)。
prototype.js は index.html と同じディレクトリにアップロードしてください。
3.モジュールの作成
MT3.3x の場合、[テンプレート] - [テンプレートを新規作成] で、「最近のエントリー」用のテンプレートを作成。各項目には下記を設定。
- テンプレート名:最近のエントリーAjaxモジュール(名前は何でもいいです)
- 出力ファイル名:recentEntries.html
- このテンプレートにリンクするファイル:(設定不要)
- 再構築オプション:チェックする
- テンプレートの内容:下記
<div class="sidetitle"> Recent Entries </div> <div class="side"> <MTEntries lastn="10"> <a href="<$MTEntryPermalink$>" title="e<$MTEntryID$>"><$MTEntryTitle$></a><br /> </MTEntries> </div>
4.テンプレートの修正
インデックステンプレートや各アーカイブテンプレートで「最近のエントリー」を表示させているタグを、下記に置き換えます。
<div id="entries"></div>
<script type="text/javascript">
//<![CDATA[
getFile('<MTBlogURL>recentEntries.html', 'entries');
//]]>
</script>
getFile のパラメータには、Ajax で取得したいファイル名(3項のファイル名)と、その id 属性(上記リストの1行目の div の id 属性に設定した属性値)を設定してください。
5.JavaScript の追加
下記のスクリプトを外部ファイル(例えば ajaxUtil.js )として保存し、index.html と同じディレクトリにアップロードしてください。
function getFile(url, id) {
url = url + "?" + Math.random();
new Ajax.Updater({success: id},
url, {
method: 'get',
onComplete: end,
onFailure: error
});
return false;
}
getFile の中で prototype.js の Ajax.Updater を呼び出しています。
prototype.js は Ajax.Request が一般的ですが、取得したデータの表示位置をダイナミックに振り分けることができません。Ajax.Updater を用いれば関数起動時に id 属性(=取得データの表示位置)を指定できるので、複数のリストをこのスクリプトひとつで賄うことができます。
Ajax.Updater の解説は下記に詳しく書かれています。
6.script 要素の追加
3のスクリプトを読み込むため、テンプレートに script 要素を </head> の直前に追加。
<script type="text/javascript" src="<$MTBlogURL$>ajaxUtil.js"></script>
7.モジュールの内容を常に更新する
prototype.js + IE では、モジュールの内容が更新されても、インクルード元のページの更新では最新の内容が反映されない事象が発生します。
その対策として、URL にランダムなクエリーを与えることで(下記)、モジュールの内容を毎回更新するようにしています。
url = url + "?" + Math.random();
参考ページを失念してしまったので、これにつきましては分かり次第掲載します。また他のライブラリであればOKとか、エレガントな実装等、さらに良い方法がありましたらご教示ください。
8.JavaScript を利用する場合のテクニック
「サイドメニューの折りたたみ」や「ツリー化」、あるいは「新着表示」等、リストに対して JavaScript を適用させたい場合、起動用の script 要素の挿入位置に気をつける必要があります。
下は4項のリストに折りたたみのスクリプト(青色)を埋め込んだ失敗例です。
<div id="entries"></div>
<script type="text/javascript">
//<![CDATA[
getFile('recentEntries.html', 'entries');
FoldNavigation('newentry','on',false);
//]]>
</script>
このようにインクルード元にインクルード先を制御するスクリプト(この例では FoldNavigation)を記述しても、 スクリプトが実行されるタイミングでは該当のリストが存在しない(=非同期で取得される)ためエラーになります。
モジュール自体にスクリプトを埋め込んだ場合も、正常に動作しないようです。
これを解決するには、Ajax でモジュールが取得された後にスクリプトを実行するようにします。例えば5項の ajaxUtil.js に下記の関数を追加します。
function end(req) {
if(req.responseText.match(/id="newentryname"/)){
FoldNavigation('newentry','on',false);
return;
}
}
これは5項の onComplete で起動される関数です。当サイトで公開している Ajax 月送りカレンダーもこの方法で休日表示のスクリプトを起動しています。
2007.08.20
3項に再構築オプションの設定の説明を追加しました。
.htaccess によるリダイレクト
PHPモジュール化やページ分割のカスタマイズを行った場合、ファイルの拡張子が .html から .php に変更になります。拡張子を変更すると、他サイトからそのファイルにリンクを貼っている場合、デッドリンク(404 Not Found)になってしまいます。
ここでは .htaccess を用いたリダイレクト(転送)によりデッドリンクを回避する方法を紹介します。
動作を簡単に説明すると、.htaccess という特殊なファイルに
hogehoge.html へのアクセスを hogehoge.php に転送する
という内容を設定し、一定の場所に配置しておくだけで hogehoge.html へのアクセスが自動的に hogehoge.php に転送されます。hogehoge.html の実体がなくても大丈夫です。
1..htaccess のフォーマット
.htaccess でリダイレクトをするための正式なフォーマットは、
RedirectPermanent URL-path URL
となります。URL-path が元URL、URLが転送先URLです。例えば archives/hogehoge.html を 同じディレクトリの hogehoge.php に転送する場合は
RedirectPermanent /blog/archives/hogehoge.html http://user-domain/blog/archives/hogehoge.php
という内容になります。ドメインを移行する場合も同様です。
フォーマットの URL-path は、ドキュメントルートからのパス(root からの絶対パスではありません)を指定し、先頭に "/" を付与してください。「ドキュメントルート」とはWebサーバがHTMLファイルを公開するためのディレクトリを意味します。
もう少し具体的に説明します。上記の例ではドメインが
http://user-domain/
で、そのドキュメントルートが
/path/to/htdocs
と仮定します。
ドメイン(つまりドキュメントルート)の配下に blog というディレクトリを作り、そこにブログの index.html が配置されている場合、index.html までの絶対パスは
/path/to/htdocs/blog/index.html
となります。この場合 .htaccess に記述すべき URL-path は、
/blog/~
と、/blog で開始させます。これが前述の「ドキュメントルートからのパス」という意味です。
ドキュメントルート直下、つまり /path/to/htdocs 直下に index.html を配置している場合は .htaccess に /blog を記述する必要はありません(ただし archives ディレクトリ等がある場合はそれを記述します)。
2..htaccess のアップロード先
.htaccess をアップロードするディレクトリは、ドキュメントルートでも、サイト・パス(ブログの index.html があるディレクトリ)でも大丈夫です。
3..htaccess 生成
.htaccess のリダイレクトの設定は、1ファイルに対して1行ずつ書かなければなりません。例えば、エントリーアーカイブ100ファイルを転送する場合、転送の設定を100行書く必要があります。
この手間を省くためにインデックステンプレートを用いて .htaccess ファイルを一気に生成します。
以下、.htaccess の作成手順です。
3.1 .htaccess 用テンプレート作成
管理メニューの「テンプレート」→「インデックス」で「テンプレートを新規作成」をクリックし、次ページで下記を設定します。
- テンプレート名:リダイレクト(何でもいいです)
- ファイル:htaccess.txt
- テンプレートの内容:下記
<MTArchiveList archive_type="Individual">
RedirectPermanent /blog/archives/<$MTArchiveDate format="%Y/%m"$>/<MTEntries><$MTEntryLink$></MTEntries> <$MTBlogURL$>archives/<$MTArchiveDate format="%Y/%m/%d_%H%M"$><MTEntries>.php</MTEntries>
</MTArchiveList>
<MTArchiveList archive_type="Category">
RedirectPermanent <$MTArchiveLink$>index.html <$MTBlogURL$>archives/cat<$MTCategoryID$>/index.php
</MTArchiveList>
<MTArchiveList archive_type="Monthly">
RedirectPermanent <$MTArchiveLink$>index.html <$MTBlogURL$>archives/<$MTArchiveDate format="%Y/%m"$>/index.php
</MTArchiveList>
リストは上から順に、エントリーアーカイブ/カテゴリー・アーカイブ/月別アーカイブを転送する設定になっています。転送が必要なアーカイブのみを設定してください。
3.2 注意事項
このリストは旧URLのファイル名をデフォルトの状態で生成していることを前提に作っており、この場合2つの注意事項があります。
まずこのファイルの生成は、管理メニューの「設定」→「公開」→「アーカイブ・マッピング」の「出力ファイル名」で新ファイル名を設定する前に行う必要があります。理由は旧ファイル名の生成に MTEntryLink を使用しているためです(MTEntryPermaLink を使っても構いません)。
もしすでに変更してしまっていたら「出力フォーマット」を一旦元の状態に戻して、このインデックステンプレートだけを生成するという手もあります(その際、他のアーカイブテンプレートを再構築しないように注意しましょう)。
もうひとつは、MTタグを使って URL-path を自動的に生成していますが、残念ながらMTタグのみで「ドキュメントルートからのパス+ファイル名」というフォーマットを生成することはできません(いわゆるURL形式で生成されます)。したがって、エントリーアーカイブについては MTEntryLink、カテゴリー・アーカイブ/月別アーカイブについては MTArchiveLink を使い、ファイルを生成した後、任意のエディタで開き、リダイレクトの設定で不要なドメイン部分を削除します。
上記とは別に、すでに「出力フォーマット」欄でファイル名を変更している場合は、URL-path の部分を適宜変更してください。また新URLについてもご自身の設定内容にあわせて適宜修正してください。
3.3 その他
この作業は一度でうまくいかないと思いますので、実際の新旧ファイル名と見比べながら、ファイルに設定したタグを修正することをお勧めします。またこの作業を行う前に、試しに各アーカイブについて1ファイルずつ手書きで .htaccess のリダイレクト設定を行ってみて、旧URLを開いた時に新URLへ転送されることを確認するのも良いでしょう。
4..htaccess アップロード
ファイルの内容がきちんとできたら保存・再構築し、出来上がったファイルを任意のエディタ(メモ帳)等で開き、ファイル名を .htaccess に変更して保存します。すでに .htaccess がある場合は、そのファイルに先の内容を追加します。
テンプレートの出力ファイル名をいきなり .htaccess として保存することも可能ですが、生成された瞬間に設定が有効となるので、一旦別のファイル名で作ることをお勧めします。
5.動作確認
できあがったファイルを .htaccess にリネームして、サイト・パス(index.html があるディレクトリ)にアップロードします。これで旧エントリーアーカイブ(.html)等にアクセスしてみてください。.php のファイルにアクセスできれば成功です。
6.Redirect と RedirectPermanent の違いについて
他のサイトを検索すると、Redirect ディレクティブと RedirectPermanent ディレクティブを使っている例がみられました。Apache2.0 のドキュメントを見てみると、たしかに
- RedirectPermanent 元URL 転送先URL
- Redirect permanent 元URL 転送先URL
の2つの設定方法がありますが、いずれも 301(永久に移動)のHTTPステータスコードを返すので、私の誤解がなければ振る舞いは全く同じです。ただし Redirect ディレクティブに permanent を付与しない場合は 302(一時的な移動)というHTTPステータスコードになりますのでご注意ください。
参考サイトは下記です。ありがとうございました。
Movable Type の PHP モジュール化の仕組みについて(その4:再構築オプション利用方法)
この回ではモジュール化による再構築オプションの有効な利用方法について説明します。
「再構築オプション」は各テンプレート編集画面の右上にあるチェックボックスを指します。このオプションはユーザー・マニュアル:テンプレートの編集にある通り、チェックボックスにチェックをつけるとエントリー投稿時等に再構築対象となり、逆にチェックを外すとテンプレート編集画面等から再構築をしない限り情報は更新されません。つまりモジュール化において「再構築オプション」にチェックをする・しないが、再構築時間短縮の重要なポイントになります。
ということでチェックするための目安となる表を作ってみました。
| モジュール化対象データ | 再構築が必要な契機 | チェック要否 |
| ブログタイトル・バナー・バージョン等 | 管理画面等からの変更時 | 不要 |
| カレンダー | 次表参照 | |
| 最近のエントリー | ||
| カテゴリーリスト | ||
| 月別アーカイブリスト | ||
| 最近のコメント | コメント投稿時 | 要 |
| 最近のトラックバック | トラックバック受信時 | |
チェック要否の要・不要は主観的な判断です。タイトル等の恒常的に普遍なモジュールは基本的に再構築対象とせず、「最近のコメント」「最近のトラックバック」のモジュールは「再構築オプション」にチェックをつけておかないとコメントが投稿された時にコメント内容がリアルタイムにページに反映されなくなります。
カレンダー?月別アーカイブリストについての再構築要否については再構築契機を細分化できるので、次表に分けてみました。
| データ | 再構築が必要な契機 |
| カレンダー | その日の最初のエントリー投稿時 |
| 最近のエントリー | エントリー投稿時(更新時は不要) |
| カテゴリーリスト | 件数表示:エントリー投稿時 件数非表示:新カテゴリーでのエントリー投稿時 |
| 月別アーカイブリスト | 件数表示:エントリー投稿時 件数非表示:月の最初のエントリー投稿時 |
カテゴリーリスト・月別アーカイブリストの「件数表示・非表示」の意味は次の通りです。
例えば月別アーカイブリストにエントリー件数を表示していない(=件数非表示)場合、ある月のリンク(月別アーカイブページへのリンク)を月別アーカイブリストに追加するためには、その月の最初のエントリー投稿後に「月別アーカイブリスト」のモジュールを一度だけ再構築すればよく、このモジュールは次月まで再構築する必要はありません。ただしエントリー件数を表示している(=件数表示)場合はエントリー投稿後に再構築しないと件数が反映されません。
カテゴリーリストも同様です。
基本的には、タイトル等のスタティックデータ用モジュールを除いた全てのモジュールに再構築オプションをチェックしておけば利便性が良いのですが、レンタルサーバ等で500エラーが頻発する場合、再構築オプションのチェックを外し、エントリー投稿後に必要なモジュールを個別に再構築するのが良いのではないかと思います。
削除動作については管理メニューから再構築が促されるので省略しています。
それぞれのモジュールを個別のインデックステンプレートとして登録すると、数が増えてメニューや管理が煩雑になるので、いくつかのモジュールをまとめてひとつのインデックステンプレートとするのもよいでしょう。またアーカイブページによってモジュールのレイアウトが異なる場合は、レイアウト用の中間的なモジュールを作ると個別モジュールが再利用できて便利です。
| その1:概要 |
| その2:具体的動作とMTIncludeとの違い |
| その3:変更方法 |
| その4:再構築オプション利用方法 |
Movable Type の PHP モジュール化の仕組みについて(その3:変更方法)
PHPモジュール化をする場合の具体的な変更方法です。
1.モジュールを引き込む元となるテンプレートの変更
これはメイン・ページや各アーカイブテンプレートが対象になり、以下の作業を行います。
1.1 インデックステンプレート(メインページ等)の場合
- 管理メニューの「テンプレート」をクリック
- インデックス・テンプレート欄より該当のテンプレートをクリックし、テンプレート内部のモジュール化したい部分を切り取ってメモ帳などにペースト(切り取った位置を忘れないようにコメントでマークしておくか、先に3を実施)
- テンプレートから切り出した部分を
に置き換え(filenameについては2、3項を参照)<?php readfile("filename"); ?> - XML宣言の修正
- 出力ファイル名の拡張子を .php に変更
- 保存・再構築
- .htaccess対処(必要に応じて)
- 拡張子が .html で配置されている旧ファイルを削除(必要に応じて)
4.は、テンプレートの1行目にXML宣言
<?xml version="1.0" encoding="<$MTPublishCharset$>"?>
がある場合、5.で拡張子を index.php にして表示すると、ページが真っ白になるか
Parse error: parse error, unexpected T_STRING in [...] on line 1
というようなエラーが表示されます。これはXML宣言がPHPとして誤解釈されてしまうための事象です。
これを回避するには、XML宣言を削除するか、
<? echo('<?xml version="1.0" encoding="<$MTPublishCharset$>"?>') ?>
とPHPが解釈可能なフォーマットに変更してください。
5.は、例えばメインインデックスの場合
- index.html → index.php
に変更します。これを行わないと 3.でテンプレート内に記述したPHPスクリプトが動作しません。
6?8は2項の部品化が完了してから行ってください。6.は5.でファイル名を変更することによって検索エンジンからのアクセスや PageRank 等に影響を及ぼすため、必要に応じて .htaccess によるリダイレクト(?.html でアクセスされたら ?.php を表示すること)を行います。エントリーがある程度たまっている方は .htaccess を使われることをお勧めします。詳細については別の機会に記述します。
8.は、7.の対処が不要な場合、例えばファイル名が index.html かつURLにファイル名が指定されていない場合等に行います。index.html を削除する理由は、拡張子によってファイルアクセスの優先順位が異なるためです。
例えば、新しく index.php を生成しても同じディレクトリに index.html が残っていると、サーバは index.html に先にアクセスします。つまり一般的には .html や .htm が .php より優先される訳です(厳密にはサーバの設定に依存しますが一般的にはこのようになっています)。
なお index.html を削除する前に URLで http://~/index.php まで指定してファイルの正常性を確認されることをお勧めします。生成に失敗した状態で index.html ファイルを削除するとアクセスが全て index.php に流れてしまうためです。
1.2 カテゴリー・アーカイブ/日付アーカイブ/個別エントリーアーカイブの場合
下記の手順で変更します。
- 管理メニューの「ウェブログの設定」をクリック
- 次のページ右上の「アーカイブの設定」をクリック
- 「アーカイブ」欄にある「アーカイブ・ファイルのテンプレート」に青色部分
- 個別:<$MTArchiveDate format="%Y/%m/%d-%H%M%S"$>.php
- 日別:<$MTArchiveDate format="%Y/%m/%d/"$>index.php
- 月別:<$MTArchiveDate format="%Y/%m/"$>index.php
- カテゴリー:cat_<$MTCategoryID$>.php
- 変更後、保存・再構築します。
2.モジュールの作成
次に部品となる方のテンプレートを作成します。
- 管理メニューの「テンプレート」をクリック
- インデックス・テンプレートの右上にある「新しいインデックス・テンプレートを作る」をクリック
- 下記の項目を設定
- テンプレートの名前:任意
- 出力ファイル名:任意
- テンプレートの内容:アーカイブテンプレート等から切り出したメニューリスト等のMTタグをペースト
- 再構築オプション:チェック
以下は「最近のエントリー」をモジュール化する場合の例です。
- テンプレートの名前:最近のコメント
- 出力ファイル名:recentEntries.html
- テンプレートの内容:
<div class="sidetitle" id="entryname">
Recent Entries
</div>
<div class="side"id="entrylist">
<MTEntries lastn="10">
<a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a><br />
</MTEntries>
</div>
「テンプレートの名前」は管理メニュー上で表示するだけのものですので日本語でもOKです。「出力ファイル名」はこのテンプレートが再構築された時、ローカル・サイト・パスに出力されるファイル名です。一応拡張子として「.html」を付与していますが、このファイルに直接URL指定してアクセスする必要がなければ「.txt」でも大丈夫です。なおこのファイル名が1項の元テンプレートに埋め込む filename になります。
「再構築オプション」はモジュール化で重要なキーとなる部分です。ここでは「チェック」にしていますが、具体的な内容は次回詳しく説明したいと思います。
3.パスについて
1項の filename の補足ですが、ファイル名にはパスが必要です。パスは絶対パス(ルートとなるディレクトリからファイルが配置されているディレクトリまで)または相対パス(参照元のファイルがある位置からファイルが配置されているディレクトリまで)で記述します。テンプレートと同じ位置にあればパス名は不要ですが、モジュールは各アーカイブから利用されるのが一般的ですので、一律絶対パスを用いるのが良いでしょう。
4.コメント・プレビュー/コメント・エラーでのインクルードについて
この項目は我楽さんより頂いたご質問の反映ということで急遽追加致しました。これらのテンプレートは実体が存在しない(CGIプログラムによるHTTPレスポンス)ため、設定方法が異なります。また現状ではPHPスクリプトが評価できる方法が不明であるため(環境設定に依存?)、このファイルからインクルードする場合は
<$MTInclude file="filename"$>
を用います。
5.PHPスクリプトをインクルードする場合
上記のサンプルではMTタグが記述され(て実体に展開され)ただけのファイルをインクルードしていますが、PHPスクリプトが記述されたファイルをインクルードする場合もあると思います。
例えば、いくつかのモジュールのインクルードをまとめた
<?php readfile("recentEntries.html"); ?>
<?php readfile("recentComments.html"); ?>
<?php readfile("recentTrackbacks.html"); ?>
という内容の中間的なモジュール hogehoge.php を想定します。この hogehoge.php をさらにメインインデックス等からインクルードする場合には、
<?php include("hogehoge.php"); ?>
と記述します。readfile はファイルを読み込むだけの関数ですが、include はファイルを読み込み、さらにそれをプログラムとして評価するための関数です。拡張子は実験したところ任意の名称で問題ないようですが、単体でPHPスクリプトの動作を確認する場合等を考慮して .php にする方が良いでしょう。
逆に言うと、PHPスクリプトが記述されていないファイルをインクルードする場合は
<?php readfile("?.html"); ?>
で大丈夫ということです。インクルードが何段にもなる場合は、インクルード元に近い方から include 関数を用いて、一番末端だけ readfile 関数または include 関数を使用、という構造になります。
以上です。
当初、「PHPスクリプトでないファイルの拡張子は .html でOKです」というオチにするだけの予定だったのですが、最初のサンプルで、
<?php include("http://?.html"); ?>
としていたところ、その1の Ogawa::Memoranda さんから頂いたコメントにある通り「PHPプログラムを含まないのであれば includeで読み込むのは得策ではありません」「サーバーサイドにあるファイルはURL指定する必要はありません」とのことで、記述を変更致しました。勉強不足、失礼致しました。あわせてご指摘感謝致します。
なお他のサーバにあるファイルを読み込む場合は上記のようなURL指定を行います。
ということでミイラ取りがミイラになりました。(つづく)
2006.03.17
XML宣言の修正について追記しました。
Movable Type の PHP モジュール化の仕組みについて(その2:具体的動作とMTIncludeとの違い)
それではPHPモジュール化の具体的な動作です。ブログURLというほぼ不変なデータを例に、モジュール化を利用する場合・しない場合の動作の違いを踏まえて説明します。
まずモジュール化をしない場合です。私のサイトで DisplayURL というインデックステンプレートを作り、displayURL.html というファイルを生成するものとします。テンプレートには下記の内容が設定されています。
<html>
<body>
<$MTBlogURL$>
</body>
</html>
このファイルを再構築すると
<html>
<body>
http://www.koikikukan.com/
</body>
</html>
となり、MTBlogURL が本来のURLに解釈されたスタティックページ displayURL.html が出来上がります。仮にこのファイルがメインページであれば、MTBlogURL は再構築される度に変換されることになります。
次にモジュール化をした場合の例です。同じく DisplayURL というインデックステンプレートを作り、ファイル名は displayURL.php と設定します(拡張子の理由は後述)。テンプレートには下記の内容を設定します。
<html>
<body>
<?php readfile("blogURL.html"); ?> *1
</body>
</html>
モジュール化の場合にはモジュール、つまり緑色で示した blogURL.html という部品を作っておく必要があります。そのために BlogURL という名称で別のインデックステンプレートを作り、blogURL.html を生成する設定を行います。テンプレートの中身は下記の1行です。
<$MTBlogURL$>
予めこのモジュールを単体で再構築しておくと
http://www.koikikukan.com/
という内容のスタティックページ blogURL.html が生成されます。
さて、この状態で先の displayURL.php を再構築しても
<html>
<body>
<?php readfile("blogURL.html"); ?>
</body>
</html>
と、内容は変化しません(この「変化しない」ということが重要)。そしてこの後ブラウザで displayURL.php にアクセスすると、このページのHTMLソースは、
<html>
<body>
http://www.koikikukan.com/
</body>
</html>
となり、ブラウザに
http://www.koikikukan.com/
が表示され <?php ~ ?> の部分がページ表示時に初めて変化することがお分かりになると思います。つまり displayURL.php の再構築時、MTBlogURL を変換するオーバーヘッドが少なくなるということを示しています。
ここでは MTBlogURL という単純なデータで説明しましたが、これが「最近のエントリー」や「カテゴリーリスト」、「月別アーカイブリスト」等で、しかも各アーカイブページテンプレートに対し前者の形で設定されていると、結構なオーバーヘッドになると考えられます。
上記の説明をまとめると、MTタグは再構築時に解析され・実体に変換されますが、PHPスクリプトはページを表示する時に変換された実体をインクルードします。表に示すと下記のようになります。
| MTタグ | PHPスクリプト | |
| 再構築 | 実行 | - |
| ページ表示 | - | 実行 |
再構築によるオーバーヘッドを減少させるためには、赤字で実行される部分をできるだけ青字の部分で実行できるように移行する訳です。
前回のもうひとつのパターン
<$MTInclude module="hogehoge"$>
との違いですが、これはを再構築時にモジュール hogehoge をインクルードしてスタティックページを生成するので、効果は再構築と同様という認識です。
なお、PHPがファイルを「phpプログラムである」と認識させるための条件があります。それはPHPスクリプトが記述されたファイルの拡張子が .php であるということです。*2
もしモジュール化したサンプルの拡張子が .html であれば、ブラウザに表示される際のHTMLソースは
<html>
<body>
<?php readfile("blogURL.html"); ?>
</body>
</html>
となるでしょう(つまり何も変わりません)。(つづく)
| その1:概要 |
| その2:具体的動作とMTIncludeとの違い |
| その3:変更方法 |
| その4:再構築オプション利用方法 |
*1:<?php ? ?> は「PHPスクリプト」と呼ばれるもので、PHPはこの部分を「PHPのために書かれたプログラムである」と認識して(ページを表示するちょっと前に)処理を実行します。
*2:ApacheというHTTPサーバで「拡張子 .php であればPHPを実行させる」という設定をするので、厳密に言えば環境依存です(設定によっては .html のままPHPを動作させることも可能です)が、ここでは一般的な作法に基づいて説明しています。
Movable Type の PHP モジュール化の仕組みについて(その1:概要)
ブログでは「PHPモジュール化」という言葉を耳にされる機会が少なくないと思います。このサイトでもよく用いる言葉で用語集にも掲載していますが、PHPモジュール化についての具体的な説明がなかったので改めて書いてみたいと思います。
用語集の繰り返しですがモジュールは「部品」を指します。よく使われるのはサイドバーメニューのモジュール化です。具体的には「最近のエントリー」や「最近のコメント」等のメニューリストのMTタグ部分をメインインデックスやカテゴリーアーカイブ等のテンプレートから分割して、それらをひとつひとつの部品として新たなテンプレートを作ります。
メインインデックスやカテゴリーアーカイブ・日別アーカイブ・個別エントリーアーカイブには部品となった
メニューリスト本体は存在せず、部品をインクルードするタグ
<? readfile("/blog/koikikukan/hogehoge.html"); ?>
を埋め込みます。
PHPモジュール化のメリットは、部品化による作業効率の向上に加え、再構築時の性能向上、つまり時間短縮が挙げられます。
性能の話の前に再構築について分かる範囲で説明致します。スタティックページ生成の場合、再構築を実行することによってテンプレート上の全てのMTタグがMovable Typeのプログラムで解釈され、HTML文書(スタティックページ)が生成されます。仮に半年分で100の記事があり、それらが10カテゴリーに振り分けられているとすれば、サイト全体の再構築を行った場合、計117(メインページ×1・月別アーカイブ×6・カテゴリーアーカイブ×10・個別エントリーアーカイブ×100)のHTMLページが一気に生成されることになります。
生成される情報の中にはリアルタイムな再構築が不要なデータ(ブログ名等)、あるいはエントリーやコメント投稿時のみ再構築されればよいものもあり、これらについては各アーカイブページの再構築と同時に新たに生成する必要はほとんどありません。
つまりPHPモジュール化とは、再構築を頻繁に行う必要がない情報を部品としてまとめておき、必要な時だけ再構築を実行することで時間短縮する手法と認識しています。ただし劇的な短縮を望むものではありません。
PHPを利用しない「テンプレート・モジュール(管理メニュー「テンプレート」の一番下)」を用いたモジュール化もありますが、これは単に情報を部品として分割するだけなので、性能向上というメリットはありません。もちろん作業効率向上やテンプレート編集時の視認性向上という意味ではPHPモジュール化と同様です。ちなみにテンプレートモジュールを用いる場合のインクルードタグは
<$MTInclude module="hogehoge"$>
となります。両者の違いは次回ご説明致します。(つづく)
テンプレート・モジュールの利用
ここではタイトル下にメニューを与える方法についてのメモです。参考サイトは下記です。ありがとうございました。デザインが合うようにスタイルシートは若干修正致しました。
なおこちらのサイトは訳ありで閉鎖されるようで残念です。
今回はMTIncludeというタグを使ってのモジュール化です。PHPを利用したモジュール化もありますので、Magic WhiteさんのPHP利用のテンプレートモジュール化をご覧ください(他のサイトでJavaScriptを使ったのもありました)。
1.新しいモジュールの追加
管理メニューより「テンプレート」をクリック。次の画面で一番下右の「新しいテンプレート・モジュールを作る」をクリック。
次画面で以下の情報を設定(URLは私のサイト用になってますので適宜変更ください)。
- テンプレートの名前:globalnavi
- モジュールの中身:下記
<div id="globalnavi">
<li><a href="<$MTBlogURL$>">Home</a></li>
<li><a href="<$MTBlogURL$>site.html">About</a></li>
<li><a href="<$MTBlogURL$>about.html">Profile</a></li>
</div>
2.スタイルシートの追加
下記をStylesheetに追加(場所はどこでもOK)
#globalnavi {
padding-top: 10px;
}
#globalnavi li {
padding-left: 0px;
padding-right: 10px;
display: inline;
}
#globalnavi li a,
#globalnavi li a:link,
#globalnavi li a:visited {
font-family: Verdana, Arial, sans-serif;
font-size: 12px;
text-decoration: none;
}
#globalnavi li a:hover {
font-family: Verdana, Arial, sans-serif;
font-size: 12px;
text-decoration: underline;
}
3.テンプレートにモジュールを引き込む設定の追加
各テンプレートのタイトル部分(下記)の該当位置に青色の記述を追加してください。
<div id="banner">
<h1><a href="<$MTBlogURL$>" accesskey="1"><$MTBlogName$></a></h1>
<h2><$MTBlogDescription$></h2>
<$MTInclude module="globalnavi"$>
</div>
4.スタイルシート修正
上記の設定を行ったあと再構築を実施すれば表示されると思いますが、メニュー配置位置がタイトルのパディングに依存するのとバナー部分が広がることでサイドバーのレイアウトが影響を受けますので、必要に応じて下記の部分を修正してください。
#banner {
padding-bottom:15px; ← バナー下からリンクまでのパディング
}
#links-right{
top : 95px ; ← 右サイドバーのトップからの開始位置
}
#links-left{
top : 95px ; ← 左サイドバーのトップからの開始位置
}
![]() | 図は上記のカスタマイズを行った結果です。こんな感じでタイトルの下にリンクメニューが表示されます。 |

