Hatena::Groupasakura

Sledge::チュートリアル

Sledge::チュートリアル

 本家のチュートリアルを読んでも何がなんだかよく分からないし、そもそもどんな風に便利か分からないので自分で書いてみました。

追補

  • Sledge::チュートリアル::フォーム?
  • Sledge::チュートリアル::セッション?

初期設定

ディレクトリ構成

 本家のTutorialではプロジェクトごとにディレクトリを作ることになっていますが、Sledge用のディレクトリを作ったほうが運用しやすい気がします*1

 例えばこんな感じ(VineLinuxの場合):

 /home/httpd - httpd関連置き場
     +-- html - ドキュメントルート
     +-- cgi-bin - cgi置き場
     +-- sledge - Sledge関連
         +-- lib - Perlモジュール
         +-- template - テンプレートファイル

 この場合各プロジェクト本体はsledge/lib/<プロジェクト名>以下とsledge/template/<プロジェクト名>以下に配置されることになります。


 こうしておくのは、プロジェクト毎にPerlモジュールのパス設定をしなくて済むからです。大規模なプロジェクトでないなら、こっちのほうが便利でしょう。

 /home/httpd/sledge/libを@INCに登録するのは本家に書かれている通りです。

 mod_perl環境なら、mod_perlの設定を書いている所に

 PerlSetEnv PERL5LIB /home/httpd/sledge/lib

と書いておけばいいでしょう。


データベースの作成

 セッション管理にデータベースを使う場合は、その設定をしなくちゃいけません。

 本家ではrootアカウントでアクセスするようになっていますが、多少気持ち悪いのでsledgeアカウントも作りましょう。

 % mysql -uroot -p
 mysql> create database sledge;
 mysql> use sledge
 mysql> grant all on * to sledge@localhost;
 mysql> create table sessions (
     -> id char(32) not null primary key,
     -> a_session text,
     -> timestamp timestamp
     -> );

プロジェクトの作成

 今回のサンプルはHelloWorldプロジェクトということにします。


セットアップの実行

 sledge/libの直下に移動して、sledge-setupを実行しましょう。

 % sledge-setup HelloWorld

を実行すれば、必要なスケルトンを作ってくれます。

 スケルトンの作成が終わったら、HelloWorld/Config/_common.pmを編集します。

 だいたいこんな感じ:

 $C{TMPL_PATH} = '/home/httpd/sledge/template/HelloWorld';
 $C{DATASOURCE} = [ 'dbi:mysql:sledge','sledge', '' ];
 $C{COOKIE_NAME}   = 'sledge_sid';
 $C{COOKIE_PATH}   = '/';
 $C{COOKIE_DOMAIN} = 'example.tld'; #実際には自分が使っているドメインを記入する

呼び出し元CGIの作成

 呼び出し元CGIを作ります。

 標準だとcgi-binディレクトリ以下でのみCGIが実行されるようになっていると思うので、その下にHelloWorldプロジェクト用のディレクトリとファイルを作ります。

mod_perlの設定によっては/home/httpd/perl以下が実行環境になっているかもしれません)

 % mkdir /home/httpd/cgi-bin/HelloWorld
 % cd /home/httpd/cgi-bin/HelloWorld

 そのしたにindex.cgiを作ります。

 index.cgiは、Sledgeを呼び出すためのCGIです。

 % vi index.cgi
 % chmod a+x index.cgi

cgi-bin/HelloWorld/index.cgi :

 #/usr/local/bin/perl
 use strict;
 use HelloWorld::Pages::Index;
 HelloWorld::Pages::Index->dispatch_query('.html');
 __END__

 CGIのほうはこれでおしまい。

 本体はlib/HelloWorld以下に作成します。


クラスの作成

 まずは呼び出し元CGIで唯一使っているHelloWorld::Pages::Indexクラスを作りましょう。

lib/HelloWorld/Pages/Index.pm :

  package HelloWorld::Pages::Index;
  use base qw(HelloWorld::Pages);
  use Sledge::DispatchQuery;
 
  sub dispatch_index {
      my $self = shift;
      $self->tmpl->param(cur_date => scalar localtime);
  }
  1;
  __END__

 スケルトンとして作られるHelloWorld/Pages.pmを直接使っても問題はないらしいですが、本家の忠告に従ってサブクラスにしています。

 Sledge::DispatchQueryは現在のSledgeパッケージには入っていませんが、CVSリポジトリに置かれています。ここからダウンロードしてインストールしましょう。


 唯一のサブルーチンであるdispatch_indexですが、実際にはこれが呼び出されることになります。

 基本的にはテンプレート(*.html)とdispatch_*が一対一で対応するようにしておき、テンプレートで使う変数などをここで定義することになります。

 フォームの入出力に関することも、だいたいここで記述することになります。


テンプレートの作成

 dispatch_indexに対応するテンプレートを作ります。

 % mkdir /home/httpd/template/HelloWorld
 % cd /home/httpd/template/HelloWorld
 % vi index.html

template/HelloWorld/index.html :

  <HTML>
  <BODY>
  Hello World! Current datetime is [% cur_date | html %]
  </BODY>
  </HTML>

 ''[%''と''%]''で囲まれている部分がテンプレートのコマンドになります。

 ここでは変数cur_dateを出力しています。

 cure_dateの後ろにある「| html」は、「<」「>」「&」などをHTMLエンティティに変換するように指示しています(これを「フィルタ」と言います)。


 なお、テンプレートに関する詳しいことはTemplate-Toolkitの説明をご覧ください(参考>Sledge/テンプレートの書式?)。


サンプルの実行

 これでとりあえずはSledgeを使ったプロジェクトが作られました。

 http://example.tld/cgi-bin/HelloWorld/index.cgiを呼び出すと、

 Hello World! Current datetime is Fri Feb 27 12:35:31 2004

のように出力されると思います。



index.html以外のテンプレートを呼び出す

 上記のままではtemplate/HelloWorld/index.htmlしか呼び出されません。

 次にhello.htmlを呼び出すようにしてみましょう。

template/HelloWorld/hello.html :

 <html>
 <body>
 [% IF name %]
 Hello, [% name %]!
 [% ELSE %]
 <form method="post" action="index.cgi?.html=hello">
 What is your name?
 <input type="text" name="name"><input type="submit">
 </form>
 [% END %]
 </body>
 </html>

 これでhttp://example.tld/HelloWorld/cgi-bin/index.cgi?.html=helloを呼び出すとhello.htmlが呼び出されるように――なりません。

 Internal Serverエラーが出ると思います。

 これはHelloWorld::Pages::Indexに、このテンプレート(hello.html)に対応したdispatch_helloというメソッドが必要だからです。そこで以下のように追加します。

lib/HelloWorld/Pages/Index.pm :(追加分)

 sub dispatch_hello {
     my $self = shift;
     my $name = $self->r->param("name");
     $self->tmpl->param(name => $name);
 }

 これで無事にtemplate/HelloWorld/hello.htmlが呼び出されるようになったはずです。http://example.tld/HelloWorld/cgi-bin/index.cgi?.html=helloを実行してみましょう。


index.cgi?.html=helloとする意味は?

 「index.cgi?.html=hello」の「hello」はテンプレートを''hello''.htmlに設定してdispatch_''hello''を呼び出すことを指示しています。~

 「.html」はどのテンプレート/dispatchを呼び出すかを指定しています。これはindex.cgiでこのように記述して

HelloWorld::Pages::Index->dispatch_query('.html');

「.html」を使うように指定していたためです。これは好きなものに変更できます。


※もっと便利な方法をSledge::Tips?に追加しました。


hello.htmlとdispatch_helloは何をやっているのか?

 hello.htmlでは

  • テンプレート変数nameが定義されていれば下記を出力する
 Hello, <入力した名前>!
  • テンプレート変数nameが未定義なら、名前の入力をうながすフォームを出力する
 What is your name? [          ][submit]

ようになっています。

 dishpatch_helloではテンプレート変数にフォームから送られてきたデータを設定しています。

 $self->r->param("name")によりフォームのnameを取り出して、$self->tmpl->param(name => $name)によりテンプレート変数を設定しています。~


dispatch_*と*.htmlを増やす

 あとは必要に応じてdispath_*と*.htmlを増やしていきましょう。



→Sledge::もうちょっと詳しい使い方?

*1:規模が大きくなるとそうでもないのかもしれませんけど。