Pagingモジュールがページを分割する仕組み
■TypePadのアーカイブページ生成の仕組み
前回公開したPaginモジュールの仕組みを理解するには、まずTypePad自体がどういう手順でアーカイブページ(カテゴリーページ)を生成しているかを理解する必要があります。
TypePadを独自テンプレートで利用されている方ならご存じのように、デザインを決定するテンプレートには通常のHTML以外にMTタグと呼ばれるMovable Type互換のテンプレート用タグが含まれています。
記事を作成したときやブログの再構築をしたときに、このMTタグが通常のHTMLタグに展開されて、サーバー上に静的なHTMLファイルを生成するのです。
そしてカテゴリーページなどのアーカイブページではテンプレート内のMTタグの内、<MTEntries>と</MTEntries>に挟まれた部分を該当するエントリーの数だけくり返すようにして展開されます。
ものすごくシンプルにイメージすると、
[エントリー群より前の部分の表示を指定したテンプレート]
<MTEntries>
[個々のエントリーの表示を指定したテンプレート]
</MTEntries>
[エントリー群より後の部分の表示を指定したテンプレート]
が、↓こんな感じ
[エントリー群より前]
[エントリー1]
[エントリー2]
[エントリー3]
[エントリー4]
[エントリー5]
[エントリー群より後]
に展開され、サーバー上にHTMLファイルとして生成されます。
記事が作成されたり再構築されてサーバー上にファイルが生成された時点でエントリー群は展開されているのですから、後からページング(ページ分割)は不可能と思えますし、現に今まで実現していなかったのです。
しかしここで自分が着目したのは、PC側に送られてくるのはサーバー上のHTMLファイルそのものではなく、もう一段階展開されたものであることです。
そこで登場するのがSSIと呼ばれる技術です。
■SSI(Server Side Include)とは
SSIとは「Server Side Include」の略で、直訳すると「サーバー側での差し込み」といったところでしょうか。
一言で言うとサーバーがHTMLファイルをクライアント(PC側)に渡す前に、ちょっとした加工を加えてくれる便利なコマンド群です。
Pagingモジュールの根幹を成しているのはこのSSIです。
SSIの使われ方でよく例に出されるのは、HTMLファイルの最終更新日やファイルサイズを自動的に書き込んだり、サイトでどのページにも共通するヘッダー部やフッター部を共通ファイルにまとめておいて、ページが呼ばれるたびに自動で差し込んだりする用途です。
普段意識することはあまりないでしょうが、後者の技術はココログなどTypePad系ブログにも使われています。
思い出してみてください。通常デザインを変えると再構築という作業が必要となりますが、サイドバーやタイプリスト(マイリスト)の変更に関してはなぜかこの作業が必要ありません。
それはサイドバーやタイプリストの内容が別ファイル化されており、サイドバーやタイプリストの変更時にはそのファイルだけが自動更新され、各ページをPC側に送るときにSSIでそれらを差し込んでいるからなのです。
SSIにはサイトの更新を楽にするいくつかのコマンドが用意されていますが、プログラミング言語と呼べるような高度なものではなく、ほんとに限定的な機能しかありません。。
実のところPagingモジュールでも以下の6種類のコマンドしか使っていません。
変数の代入:
<!--#set var="変数名" value="値" -->
変数の表示:
<!--#echo var="変数名" -->
条件分岐構文(いわゆるif文):
<!--#if expr="条件式" -->
<!--#elif expr="条件式" -->
<!--#else -->
<!--#endif -->
無理してたったこれだけのコマンドしか使わなかったわけじゃありません。SSI自体がHTMLに含まれたコマンドを上から下に順に処理するだけで、いわゆるfor文やwhile文のようなループ制御はありません。配列変数もないし、それどころか足し算、引き算すらできないのです。
唯一活路を見いだしたのは、if文で一応まともな正規表現が使えることでした。
■Pagingモジュールのやっていること
根幹であるSSIが難しいことは何もできないため、Pagingモジュールもそれほど難しいことをやってるわけじゃありません。
導入時のことを思い出してください。
エントリーの繰り返しを意味するMTタグ<MTEntries>、</MTEntries>それぞれにPagingモジュールを構成する合計4つのモジュールを挿入するように書き換えました。
最初のMTタグの展開にそれを書き加えると、
[エントリー群より前の部分の表示を指定したテンプレート]
[paging-initializeモジュール]
<MTEntries>
[paging-entry-topモジュール]
[個々のエントリーの表示を指定したテンプレート]
[paging-entry-bottomモジュール]
</MTEntries>
[paging-navigationモジュール(paging-navigation-scriptモジュールも内包)]
[エントリー群より後の部分の表示を指定したテンプレート]
が、↓こんな感じ
[エントリー群より前]
[paging-initializeモジュールの実体であるSSI]
[paging-entry-topモジュールの実体であるSSI]
[エントリー1]
[paging-entry-bottomモジュールの実体であるSSI]
[paging-entry-topモジュールの実体であるSSI]
[エントリー2]
[paging-entry-bottomモジュールの実体であるSSI]
[paging-entry-topモジュールの実体であるSSI]
[エントリー3]
[paging-entry-bottomモジュールの実体であるSSI]
[paging-entry-topモジュールの実体であるSSI]
[エントリー4]
[paging-entry-bottomモジュールの実体であるSSI]
[paging-entry-topモジュールの実体であるSSI]
[エントリー5]
[paging-entry-bottomモジュールの実体であるSSI]
[paging-navigationモジュールの実体であるSSI(paging-navigation-scriptの実体であるJavaScript)]
[エントリー群より後]
に展開されます。
ここまでくるとプログラミングができる人なら容易に想像できると思うんですが、Pagingモジュールとは端的に言うとSSIの条件分岐(if文)を上から順にpaging-entry-top&paging-entry-bottom間でくり返しおこなって、各エントリーの表示、非表示を切り替えているだけなのです。
実際には言うは易しで、やり方は思いついたが加算減算すらできないというSSIの制限の中でこれを実現するのは骨の折れる作業でした。
とくにやたらと長いpaging-navigationの正体は、その大部分が次のページ&前のページのエントリー数を数えて数字に変換しているだけなんです。
モジュール内では繰り返しの数だけ余計な空白が入ったりしないように改行無しでぎっちり詰め込んだので読みづらいですが、ちゃんと改行してやれば、初心者が書いたようなif文の羅列なんで、プログラミング初心者でも流れは簡単に読めると思います。
興味があったら解読して苦労の跡を偲んでやってくだされ。


コメント