Movable Type (MT) ユーザにとって、カテゴリの並べ替えと同じくらいポピュラーな悩み(?)として、カテゴリー・アーカイブのページ分割がある。これは Seesaa ブログを使っていた時もそうだったのだけれども、月別アーカイブなどとは違って明確な区切りがないカテゴリー・アーカイブは際限なくエントリーが蓄積されて行ってしまい、エントリーが多ければ多い程、いち HTML ページが肥大してしまう。
いっそのこと、カテゴリーなんて概念を使わないようにしようか、とも考えた。ストーリーが纏まっていなければ、ばっさり諦めることもできるかもしれない。もしくは、タイトルだけの索引ページにしてしまうか。タイトルだけなら、そのページを開くのが大事になるほど成長するまでには、じゅうぶんな猶予ができるだろうから。
さて。
記事数が少ないうちから心配したところで切迫感もないから気は進まない。どうにかアイデアを出したとしても効果は知れたもの。でも将来のことを思えば、なんらかの対処をいまのうちからやっておかないと、いざというときに困ることになる、だろう、か(?)。ということで、ほかのところではどうしているのかとまずは調査。
ざっと Google で拾い見してみると、ほとんどは、 "MTPaginate" というプラグインに頼るために、まずサイトを PHP 化している。ページ分割のためにサイトを PHP 化するだなんて順序が違う気がする。でもこれでないとできないのであれば、致し方ないかも知れない。──この方法しかないのだろうか。
できれば PHP なんかに頼りたくない。 MT は Perl で書かれているのに、なんで PHP ? などと思っていたら Perl でページ分割を実現しているものを見つけた[関連1]。ただ、これは(これも?)ダイナミック・パブリッシングが前提のようだ。オリジナルのプラグインもいっしょに提供されていた。
PHP を嫌うならば、これを用いてダイナミック・パブリッシング、そうするしかないのかしら? 再構築の際に、分割したいぶんだけの静的ファイルを、せっせと作るようにするとか、そういう仕組みでは駄目なのだろうか。──だれもやっていない(やっているのを見つけられなかった)ので、駄目なのかも知れない。理屈としては、 MT はソースがいじれるので、できないことではないのだろう、でもアイデアとしては、ダメなんだなと思われた。だって誰もやってなさそうなんだもの。フウム。どうしたものか。
たしかに、ダイナミックなページのほうが(システムを「ダイナミック・パブリッシング」にすることではなく、単に動的なページとして)、ページ分割の実現も簡単そうだ。いちページに表示させるエントリー数と、何ページ目かを指定して持って来たエントリーを、テンプレートをとおして整形して表示させればいいのだろう。と、言うのは簡単なことだけれども、でもできないことはないと思って、ひとつチャレンジして作ってみようかしら、と思った。ページをめくる、フロントエンドになるべく CGI プログラムを、 Perl で。カテゴリ・アーカイブに、そのフロントエンドを使えば、サイトのシステムはそのままでいいし( PHP 不要)、 MT の設定をいろいろいじってダイナミック・パブリッシングにすることにも頼らない。そういう CGI プログラムが作れれば、ベターかしらん。
そう思って、とりあえず何か参考にできる足がかり的なものはないかと MT のライブラリをブラウズしてたら、 MT::App::Viewer というものに行き着いた。これは mt-view.cgi の中身のようだ。はて、 mt-view.cgi は何をするのかとしばし中を追ってみてみると、これってつまり、いまやりたいことをやっているのではなかろうか(!?)
ものは試しだと、さっそく HTTP 経由でアクセスしてみると、こんなメッセージが出た。
環境設定ファイルの「SafeMode」を設定してください。
設定ファイルを開くと、 "SafeMode" がコメントアウトされていた。おもむろにコメントを外す。コメントを外して SafeMode がオフになると、 unsafe なんだろうか。それはまたあとで調べよう。再度、アクセスする。
MT::App::Viewer は、自身の URL にある PATH_INFO を見て動作を変える模様だ。 PATH_INFO の先頭のスラッシュ '/' の次に、数字が続いていることを期待していて、それが blog_id となっていた──なぜなら、それがなかったら、 "No blog_id というメッセージを作っていたから。
コードはそれほど長くもなく、しばらく見つめていたらば、とりあえずカテゴリ・アーカイブを呼び出すには、次のようにすればよいのではないかと思われた。
http://MT_HOME/mt-view.cgi/${blog_id}/section/${cat_id}
$blog_id はブログ ID 、それから cat_id が、カテゴリ ID 。いずれも数字で構成されている。これらは管理画面をいじっていれば、 URL の中に含まれていたりするのでそこで気がつくことができる。そして、 "section" という定数が、ヒントになっているようだ。これでもって、あるカテゴリを呼び出してみた。こんなふうに。
http://MT_HOME/mt-view.cgi/1/section/2
すると、期待どおりのページが出た。カテゴリ ID が 2 の、カテゴリー・アーカイブが表示された。
なるほどこれを、このアプリケーションを基にすれば、ページを生成するのはいちから作り出すよりもぜんぜん簡単にできそうだと思えた。あとは、このアプリケーションに、ページに表示させる件数と何ページ目を出すかというパラメータを、取り扱えるように拡張すればいい。
と、見付け物だと思っていたら、ソースの中では更に、パラメータ 'limit' と 'offset' を受け付けるようになっているではないか。その名前がすごくあやしい。これはもしやと閃いて、そのパラメータをクエリーストリングとして渡してみた。たとえば、次のように:
http://MT_HOME/mt-view.cgi/1?limit=5&offset=5
するとどうだろう。6件目の記事から、続く5件が表示されたではないか(!)。おー。──って、既にあるの? と逆に不思議に思った。
みんななぜ、これを使わないのだろう。もしやこれはじぶんが気づかないだけで、けっこうポピュラーなツールだったんだろうかと、 Google に訊いてみた。でもヒットしたのは200件ちょっとしかなく、その殆どは、 MT をセットアップするさいに、 *.cgi を chmod +x することについてのたったそれだけのことだった。唯ひとつだけ(といってもよいほど)、 mt-view.cgi について注目されていた記事があった[参考2]。でもその記事も、対象としている MT のバージョンも、少々ふるい様子。そして、そのページにも書かれていることには、 mt-view.cgi はメンテされていないものだ、ということだった。
メンテされておらず、マニュアルにもないとなると、誰も使おうという気がしないものかもしれない。それとも SafeMode をオフにすることの代償が大きすぎるのだろうか。 SafeMode を調べると、これも、くわしく言及している記事が見つからなかった。 MT のマニュアルを見ると、 "SafeMode" にはこうある。
「セーフ・モード」がオンになっていると、セキュリティなどの問題についての警告機能がオンになり、テンプレートを.cgiやその他の拡張子を持つファイルにリンクさせる機能などの小規模な機能がオフになります。 セーフ・モードはデフォルトではオンですが、SafeModeを0に設定すると、オフにできます。
ふむ。「警告機能がオンに」なるというのは、あくまで「警告機能」なのだから、サイト自体が unsafe なものになるという解釈には、いまひとつ繋がらない気がする(都合のよい解釈?)。あまり気にする所でもないもかも知れない。
ではなぜ、この一見便利そうな mt-view.cgi が日の目を見ないのだろうか。
──なるほど、メインページを指定したときに動作するところはちょうど動いたけれども、 それ以外の呼び出し方の所では、 'limit' も 'offset' も考慮されていなかった。途中で投げ出したような、そんなふうに見ようと思えば、見えなくもなかった。
でももしこれが使えるのだったら、当初の目的はおおよそ達成してしまうようにも思える。つまり、フロントエンドはもうあるとして、あとはパラメータ 'limit' と 'offset' を、制御できるようなテンプレート・タグを、プラグインで作って使えるものに仕上げればよいのではなかろうか。
ということで、以上はすべて長い前置きで、そのプラグインを作ってみて、そして使ってみた、というのが主題である。
まず、 MT::App::Viewer を少々改造してみた。その結果、メインページだけではなく、カテゴリー・アーカイブでも、パラメータ 'limit' と 'offset' を受け付けて、その範囲のエントリーのみをページとするように動くようにした(日付アーカイブも考慮したけれど、テストしてない。ちゃんと動くかしら??)。
それから、プラグイン。プラグインは初めて作ってみるけれども、適当なほかのプラグインを開いてみたりして、なんとなく出来た。要は、 CGI パラメータ 'limit' と 'offset' を取得して、タグとして扱えるようにすることなんだけれども、CGI の入力を MT が既に取得してパースしてどこかに保持しているであろうそれに、どうやってアクセスしたらよいのかわからなかった。結局、プラグインの中で CGI (CGI.pm) オブジェクトを作って、そこから取得してしまった。こんな方法は、ぜひ止めたい。けれどもとりあえず出来たので、そのまま使うとする。
あとは、いちページに並べるエントリーの数の設定をどうするか。最初は、プラグインの設定として持たせておこうと、頑張って作ってみたのだけれども、メインページについて、ブログの設定の中に同様の設定があることに気がついて、結局その値を使うことにした。なぜなら、メインページが5件表示となっているのに、プラグインが7件表示だと、先頭からページをめくるときに6、7件目がページとページの間に隠れてしまうから。
... と、なにはともあれ、いちおう動作するまでに作り込んでみて、早速つけてみた(このブログ)。
メインページのテンプレートには、プラグインで新しく加わったタグを用いて、次のページと前のページへのリンクを貼付けて、再構築する(これは静的ページ)。これで、7件表示のページに、次の7件と、前の7件を表示するリンクができた。あとカテゴリー・アーカイブについては、もともとのリンクの URL から mt-view.cgi を用いた URL に変更するために、 Apache の RedirectMatch ディレクティブをセットした。
RedirectMatch .*/hpod/category/(.+)/(.*)$ http://hwat.sakura.ne.jp/mt/mt-view.cgi/2/section/$1
これは、カテゴリ・アーカイブの出力フォーマット(パス)に、カテゴリー ID を持たせていたから実現できた。
category/<MTCategoryID>/index.html
表示しているアーカイブでの総エントリー数を取得すれば、それを 'limit' で割って、ページ番号を作ることも出来そうだ(TODO)。あと、先頭と末尾を検知するコンテナタグをつくれば、完璧かしら(TODO)。うむ、われながら、なかなか上出来かも知れないぞ :-)
ただ気がかりなのは、この方法が果たしてよい手法なのかどうなのか、ということナノダ。いまひとつ自信が持てないのは、なぜ。
ダウンロード:
(追記:ふるいバージョンのリンクを消しました。最新版へのリンクを記載しています。最新版ではパッチとプラグインと、べつべつになっています。)
MTViewCGIPageController-0.01.tar.gz
参考:
- [1] 再構築を不要にするカスタマイズ(Perl版ダイナミック・パブリッシング) (The blog of H.Fujimoto)
- [2] mt-view.cgiを使ってみる (Ogawa::Memoranda)
TB: