昼休みの時間にCatalystでMixiを作ってみよう
動作環境
perl 5.8.8
MySQL
Catalyst-Runtime 5.7001 + Catalyst-Devel 1.0
Template-Toolkit + DBIx-Class
CPANモジュールたくさn。
mixiっぽいって事でlixiと命名・・
# catalyst.pl lixi created "lixi" created "lixi/script" created "lixi/lib" created "lixi/root" created "lixi/root/static" created "lixi/root/static/images" created "lixi/t" created "lixi/lib/lixi" created "lixi/lib/lixi/Model" created "lixi/lib/lixi/View" created "lixi/lib/lixi/Controller" created "lixi/lixi.yml" created "lixi/lib/lixi.pm" created "lixi/lib/lixi/Controller/Root.pm" created "lixi/README" created "lixi/Changes" created "lixi/t/01app.t" created "lixi/t/02pod.t" created "lixi/t/03podcoverage.t" created "lixi/root/static/images/catalyst_logo.png" created "lixi/root/static/images/btn_120x50_built.png" created "lixi/root/static/images/btn_120x50_built_shadow.png" created "lixi/root/static/images/btn_120x50_powered.png" created "lixi/root/static/images/btn_120x50_powered_shadow.png" created "lixi/root/static/images/btn_88x31_built.png" created "lixi/root/static/images/btn_88x31_built_shadow.png" created "lixi/root/static/images/btn_88x31_powered.png" created "lixi/root/static/images/btn_88x31_powered_shadow.png" created "lixi/root/favicon.ico" created "lixi/Makefile.PL" created "lixi/script/lixi_cgi.pl" created "lixi/script/lixi_fastcgi.pl" created "lixi/script/lixi_server.pl" created "lixi/script/lixi_test.pl" created "lixi/script/lixi_create.pl"
(おもったけどデフォルトページ用のstatic関係いらんのだけど、書き出さないオプションあるんでしょうか)
#cd lixi
viewの作成
# script/lixi_create.pl view TT TT exists "/home/test/public_html/lixi/script/../lib/lixi/View" exists "/home/test/public_html/lixi/script/../t" created "/home/test/public_html/lixi/script/../lib/lixi/View/TT.pm" created "/home/test/public_html/lixi/script/../t/view_TT.t"
lixi_dbにはuserdataとfriendlistの二つのテーブルがある。
userdata +--------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+--------------+------+-----+---------+----------------+ | uid | int(11) | | PRI | NULL | auto_increment | | account | varchar(32) | | | | | | password | varchar(255) | | | | | | display_name | varchar(255) | | | | | | profile | text | | | | | | email | varchar(255) | | | | | +--------------+--------------+------+-----+---------+----------------+ friendlist +-------+---------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+----------------+ | id | int(11) | | PRI | NULL | auto_increment | | uid | int(11) | | | 0 | | | fid | int(11) | | | 0 | | +-------+---------+------+-----+---------+----------------+
こんなかんじ。
ヘルパーでModel作成
# script/lixi_create.pl model DBIC DBIC DBI:mysql:lixi_db lixi password exists "/home/test/public_html/lixi/script/../lib/lixi/Model" exists "/home/test/public_html/lixi/script/../t" created "/home/test/public_html/lixi/script/../lib/lixi/Model/DBIC.pm" created "/home/test/public_html/lixi/script/../lib/lixi/Model/DBIC" created "/home/test/public_html/lixi/script/../lib/lixi/Model/DBIC/Friendlist.pm" created "/home/test/public_html/lixi/script/../lib/lixi/Model/DBIC/Userdata.pm" exists "/home/test/public_html/lixi/script/../t" created "/home/test/public_html/lixi/script/../t/model_DBIC-Friendlist.t" exists "/home/test/public_html/lixi/script/../t" created "/home/test/public_html/lixi/script/../t/model_DBIC-Userdata.t"
これでModelのスクリプト作成
指定したDBの中身を読み込んでくれる賢いやつ。
テストサーバー起動
# script/lixi_server.pl [debug] Debug messages enabled [debug] Loaded plugins: .----------------------------------------------------------------------------. | Catalyst::Plugin::ConfigLoader 0.06 | | Catalyst::Plugin::Static::Simple 0.14 | '----------------------------------------------------------------------------' [debug] Loaded dispatcher "Catalyst::Dispatcher" [debug] Loaded engine "Catalyst::Engine::HTTP" [debug] Found home "/home/test/public_html/lixi" [debug] Loaded tables "friendlist userdata" [debug] Loaded components: .-----------------------------------------------------------------+----------. | Class | Type | +-----------------------------------------------------------------+----------+ | lixi::Controller::Root | instance | | lixi::Model::DBIC | instance | | lixi::Model::DBIC::Friendlist | class | | lixi::Model::DBIC::Userdata | class | | lixi::Model::DBIC::_db | class | | lixi::View::TT | instance | '-----------------------------------------------------------------+----------' [debug] Loaded Private actions: .----------------------+--------------------------------------+--------------. | Private | Class | Method | +----------------------+--------------------------------------+--------------+ | /default | lixi::Controller::Root | default | '----------------------+--------------------------------------+--------------' [info] lixi powered by Catalyst 5.7001 You can connect to your server at http://localhost:3000
こんな感じでテストサーバーを動かすとデバッグを表示してくれます。
- rをつけて起動するとソースをいじる度にサーバーを再起動してくれます。
それではhttp://localhost:3000/にアクセスしてみよう。(URLは自分の環境に変えるべし)
アクセスするとCatalystデフォルトページがひょうじされる。
このページはlixi/lib/lixi/Controller/Root.pmにある
sub default : Private { my ( $self, $c ) = @_; # Hello World $c->response->body( $c->welcome_message ); }
が表示してくれていますが、昼休みがおわっちゃうので
さっさとlixi用に変えてみます。
lixi.pm
package lixi; use strict; use warnings; use Catalyst qw/-Debug ConfigLoader Static::Simple Charsets::Japanese/; our $VERSION = '0.01'; __PACKAGE__->config( name => 'lixi', charsets => 'Shift_JIS', ); __PACKAGE__->setup; 1;
use Catalyst qw/-Debug ConfigLoader Static::Simple Charsets::Japanese/;
ここには使うCatlyst::Pluginのモジュールを
Carsets::JapanesでConfigにかいてあるShift_JISに変換してくれる。
とりあえずやっぱりログインするためのページが必要かな。
Mixiみたいなログインページをトップページに表示してみる。
トップページや、他のコントローラー以外のURLだった場合の表示が
Root.pmにある default : Privateだ。
Root.pmにおかないでlixi.pmにおいても動作するけど、Root.pmにかいておこう。
lixi/lib/lixi/Controller/Root.pm
package lixi::Controller::Root; use strict; use warnings; use base 'Catalyst::Controller'; __PACKAGE__->config->{namespace} = ''; # デフォルトの処理 sub default : Private { my ( $self, $c ) = @_; # テンプレート設定 $c->stash->{template} = 'login.tt'; } # デフォルトの最後 sub end : Private { my ( $self, $c ) = @_; # Viewに処理をなげる $c->forward('lixi::View::TT'); } 1;
login.ttはlixi/root/においてあって、特に指定しない場合にはlixi/rootからファイルを探す。
login.tt
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html lang="ja"> <head> <meta http-equiv="content-type" content="text/html;charset=shift_jis"> <title>welcom lixi!</title> </head> <body bgcolor="#ffffff"> [% error_msg %] <form id="FormName" action="/login" method="post" name="FormName"> あかうんとめい <input type="text" name="account" size="24"> <p>ぱすわーど <input type="password" name="password" size="24"></p> <p><input type="submit" name="" value="login"></p> </form> <p></p> </body> </html>
これでログインページを表示するようになった。
ログインチェックは/loginとする。
Root.pmに login : Globalとかいてもいいんだけど、分けた方があとから見通しがいいので、ヘルパーにつくってもらう。 ついでにlogoutもつくっておく。
# script/lixi_create.pl controller login exists "/home/test/public_html/lixi/script/../lib/lixi/Controller" exists "/home/test/public_html/lixi/script/../t" created "/home/test/public_html/lixi/script/../lib/lixi/Controller/login.pm" created "/home/test/public_html/lixi/script/../t/controller_login.t"
# script/lixi_create.pl controller logout exists "/home/test/public_html/lixi/script/../lib/lixi/Controller" exists "/home/test/public_html/lixi/script/../t" created "/home/test/public_html/lixi/script/../lib/lixi/Controller/logout.pm" created "/home/test/public_html/lixi/script/../t/controller_logout.t"
メモメモ Template-ToolkitからCatalystにアクセスするに
A number of other template variables are also added: c A reference to the context object, $c base The URL base, from $c->req->base() name The application name, from $c->config->{ name }
上記のが使える
ログイン後のテンプレートを用意
top.tt
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html lang="ja"> <head> <meta http-equiv="content-type" content="text/html;charset=shift_jis"> <title>ようこそlixiへ!</title> </head> <body bgcolor="#ffffff"> <p>ようこそlixiへ!</p> <p>[% display_name %]</p> <p></p> </body> </html>
lixi.pmとRoot.pmとlogin.pmでちゃんとログインできるように書き直します。
lixi.pm
package lixi; use strict; use warnings; use Catalyst qw/-Debug ConfigLoader Static::Simple Charsets::Japanese Authentication Authentication::Store::DBIC Authentication::Credential::Password Session Session::Store::FastMmap Session::State::Cookie /; our $VERSION = '0.01'; __PACKAGE__->config( name => 'lixi', charsets => 'Shift_JIS', authentication => { dbic => { user_class => 'lixi::Model::DBIC::Userdata', user_field => 'account', password_field => 'password', }, }, ); __PACKAGE__->setup; 1;
追加修正した部分は認証系のCatalystPluginを利用するようにしたこと。
Authentication
Authentication::Store::DBIC
Authentication::Credential::Password
Session
Session::Store::FastMmap
Session::State::Cookie
DIBCの認証とセッションモジュール
Configには
authentication => {
dbic => {
user_class => 'lixi::Model::DBIC::Userdata',
user_field => 'account',
password_field => 'password',
},
},
をついか
Authentication::Store::DBIC でuser_classとuser_field,password_filedを設定する。
user_field => 'account'でユーザー名をMySQL::Userdataのaccountと結びつけるおまじない。
Root.pmとlogin.pmは以下のようにした
package lixi::Controller::Root; use strict; use warnings; use base 'Catalyst::Controller'; __PACKAGE__->config->{namespace} = ''; sub auto : Private { my ($self, $c) = @_; if (!$c->user_exists) { $c->detach('/login/default'); return 0; }else{ my $userdata = lixi::Model::DBIC::Userdata->search( account => $c->user); $c->stash->{display_name} = $userdata->first->display_name; } } sub default : Private { my ( $self, $c ) = @_; # TOPPAGE $c->stash->{template} = 'top.tt'; } sub end : Private { my ( $self, $c ) = @_; $c->forward('lixi::View::TT'); } 1;
Rootではauto:Privateで常にユーザーでログインしているかチェック
auto:Privateは一番最初に動作する部分
login.pm
package lixi::Controller::login; use strict; use warnings; use base 'Catalyst::Controller'; sub default : Private { my ( $self, $c ) = @_; my $req_account = $c->req->param('account'); my $req_password = $c->req->param('password'); #check if($req_account && $req_password){ if($c->login($req_account , $req_password)){ $c->response->redirect('/'); }else{ $c->stash->{error_msg} = "あかうんとめいまたはパスワードが違います"; } } $c->stash->{template} = 'login.tt'; } 1;
ログインチェックと駄目だった場合のメッセージをerror_msgにいれる
以上で適当な認証は終わり
まだまだ続く