MT4.xプラグイン作成/MTのライブラリを利用した独自アプリを作る http://www.ark-web.jp/sandbox/wiki/306.html
MT4.xプラグイン作成/MTのライブラリを利用した独自アプリを作る
MT::Boostrapを利用してMTのライブラリ(とそれによって提供されるクラス、オブジェクト)を利用した独自アプリケーション(CGI)を構築することができます。
このエントリーではMT::Bootstrapを使うと何がうれしいのか、そして、MT::Bootstrapの簡単な使い方について説明します。
参照:Movable Type オブジェクト・リファレンス - MT::Bootstrap
MT::Bootstrap
MT::Bootstrapを使うと何がうれしいのか? †
MT::Bootstrapを使うことで次のようなうれしいことが!
- MT、MT::App、MT::ObjectといったMTのライブラリが提供するクラス、オブジェクトを独自アプリケーション(CGI)で利用できる
- ↑によってSQLを直接叩なんてことをせずに、MTで保持しているデータにAPI経由でアクセスできる(MT::Object様々)
- ↑からDBに依存しない実装が可能(MT::Objectが環境差を吸収してくれる)
- 導入しているPluginが独自に定義しているMT::*クラス、オブジェクトも利用できる
- HTTPヘッダの出力、GET/POSTデータの受け取り、標準出力への出力、メールの送信など定型の処理をMTに任せてしまえる
- (やったことないけど)MTのユーザ管理、認証の仕組みも利用できる
なので、例えば、MTのユーザ別に記述したブログ数を出力する「ブログいっぱい書いた人ランキング」を表示するCGIなどが簡単に作れます。
MT::Bootstrapの簡単な使い方 †
Step by StepでMT::Bootstrapの簡単な使い方を示します。
1. 本体プログラムを作成する †
WebブラウザでURLを指定されてアクセスされるスクリプトを作成します。このスクリプトがCGIアプリケーションの本体になります。コードは以下のようになります。
#!/usr/bin/perl -w
use strict;
use File::Basename;
use lib (dirname($0) . '/') . 'lib';
use lib $ENV{MT_HOME} ? "$ENV{MT_HOME}/lib" : (dirname($0) . '/../../') . 'lib';
use lib $ENV{MT_HOME} ? "$ENV{MT_HOME}/extlib" : (dirname($0) . '/../../') . 'extlib';
use MT::Bootstrap App => 'BlogPublisherRanking';
コードはこれだけです。本体スクリプトには詳細なコードは書かずに単にMT::BootstrapにアプリケーションのMainのロジックを記述したクラス名を与えるだけです。以下、このクラスをMainクラスと呼称します。Mainクラスのクラス名はBlogPublisherRankingとしました。
use MT::Bootstrap App => 'BlogPublisherRanking';
このスクリプトを任意の名前で保存します。ここではblog_publisher_ranking.cgiとします。*1
保存したスクリプトに実行権限を与えておきます。
$ chmod a+x blog_publisher_ranking.cgi
2. Mainクラスを作成する †
Mainクラス、BlogPublisherRankingを以下のように作成します。
package BlogPublisherRanking;
use strict;
use MT;
use MT::App;
use MT::Blog;
use MT::Entry;
:
: # 利用したいMTライブラリのクラス名を列挙する
:
# MT::Appクラスのサブクラスとして定義する。
@BlogPublisherRanking::ISA = qw(MT::App);
sub init_request {
my $app = shift;
$app->SUPER::init_request(@_);
$app->add_methods( BlogPublisherRanking => \&_BlogPublisherRanking );
$app->mode('BlogPublisherRanking');
$app->{requires_login} = 0;
}
sub _BlogPublisherRanking {
my $app = shift;
my $q = $app->param;
:
: # 色々な処理
:
return '画面に表示したい文字列';
}
1;
このスクリプトをlib/配下など、blog_publisher_ranking.cgiがライブラリパスとして参照できるディレクトリにファイル名BlogPublisherRanking.pmで保存します。
Mainクラスにはアプリケーションの実際のロジックを記述していきます。
また、MainクラスはMT::Appのサブクラスとします。こうすることで、HTTPヘッダの出力、GET/POSTデータの受け取り、標準出力への出力といったCGIに特有の定型処理を自分で書く必要がなくなります。
sub init_request {
my $app = shift;
$app->SUPER::init_request(@_);
$app->add_methods( BlogPublisherRanking => \&_BlogPublisherRanking );
$app->mode('BlogPublisherRanking');
$app->{requires_login} = 0;
}
のコードで、アプリケーションに対するリクエストの取り扱いを初期化しています。
具体的には、
- app_methodsでBlogPublisherRankingというモードとこれを処理するメソッド_BlogPublisherRankingを定義し
- modeメソッドでBlogPublisherRankingを指定することでアプリケーションのモードをBlogPublisherRankingに変更し
- requires_loginに0を指定することでMTのログインなしに実行されるアプリケーションであることを明示
しています。
これによって、おおざっぱにいうと、
blog_publisher_ranking.cgiにブラウザ等でアクセス
-> BlogPublisherRankingのinit_requestが実行される
-> モードがBlogPublisherRankingなので、そのモードに対応した_BlogPubliserRankingが呼び出される
という処理が走ります。
そして、_BlogPubliserRankingで何らかの処理を行って、文字列を返すとその文字列がブラウザ等の画面上に表示されます。HTTPヘッダを自分で出力する必要はありません。
また、_BlogPubliserRankingでは、第一引数にMT::Appの参照を受け取ることができ、MT::App->paramでGET/POSTデータを取り出すことができます。
このファイルを./BlogPubliserRanking.pmなどのパスで保存します。
参照:
3. テンプレートのロードと出力構築 †
では、_BlogPublisherRankingの詳細を実装します。
sub _BlogPullisherRanking {
my $app = shift;
my $q = $app->param;
# テンプレートファイルの格納ディレクトリを設定する
$app->{plugin_template_path} = 'tmpl/BlogPublisherRanking';
# 以下のデータ構造を取得する関数(_get_sorted_publishers)があるとする
# (
# { name => 一番エントリー数の多いユーザ名, ... },
# { name => 次にエントリー数の多いユーザ名, ... },
# :
# { name => 一番エントリー数の少ないユーザ名, ... },
# )
my @publishers = &_get_sorted_publishers($app);
my %param = (
'publishers' => \@publishers,
);
# テンプレートにパラメータを適応して、結果文字列(ブログいっぱい書いた人ランキング)を生成して返す
return $app->build_page('blog_publisher_ranking.tmpl', \%param);
}
まず、
$app->{plugin_template_path} = 'tmpl/BlogPublisherRanking';
によってテンプレートファイルを置くディレクトリパスを指定します。
ここでは、スクリプト(blog_publisher_ranking.cgi)からの相対パスでtmpl/BlogPublisherRankingというディレクトリにテンプレートを置く指定をしています。
その後、必要なデータ構造(この場合、ブログを書いたランキングでソートされたMT::Authorの配列)を生成し、テンプレートに引き渡して結果文字列を生成します。
テンプレートファイルは
my $html = $app->load_tmpl('blog_publisher_ranking.tmpl', \%param);
と指定しているので、先のplugin_template_pathの指定からtmpl/BlogPublisherRanking/blog_publisher_ranking.tmplと判断されます。
テンプレートファイルの中身は
<mt:loop name="publishers"> <$mt:var name="name"$> </mt:loop>
といった形になります*2。
return $app->build_page('blog_publisher_ranking.tmpl', \%param);
build_pageで結果を生成して返します。
4. MT::Objectのロード †
書いたエントリー数が多い順にユーザ名を返す_get_sorted_publishers関数は以下のようにできると思います。
sub _get_sorted_publishers {
my $app = shift;
# MT::Authorオブジェクトを全件ロードする
my @authors = MT::Author->load();
# author_idとユーザ名,書いたエントリー数からなるハッシュ { id => author_id, name => ユーザ名, count => エントリー数 }の配列を生成する。
my @publishers = map { return { 'id' => $_->id, 'name' => $_->name, 'count' => MT::Entry->count({ 'author_id' => $_->id }) }; } @authors;
# エントリー数でソート(降順)して返す
return sort { $b->{'count'} <=> $a->{'count'} } @publishers;
}
MT::AuthorもMT::EntryもMT::Objectを継承しているのでloadメソッドで簡単に取得できるのが助かるところです。
*1 このスクリプトはblog_publisher_ranking.cgiがMT本体のディレクトリに設置されているという想定でlib、およびextlibのパスを指定しています。設置場所が異なる場合はそれにあわせて、パスを変更する必要があるでしょう
*2 詳しくはMT4.xプラグイン作成/テンプレートでループを利用する方法を参照のこと
![[PukiWiki] [PukiWiki]](image/sandbox.gif)



