CakePHPからCatalystに置き替え
メソッドとかサブルーチンとか
訳あって現在作ってたソースを
CakePHP(PHP)からCatalyst(Perl)へ移行中なのです。
文法的にはPHPとPerl似てるところもありますが、概念とか呼び方が全然違うので戸惑いの連続です。
http://www15.plala.or.jp/h-kihara-home/prog/perl/ooperl.html
------------------------------------------- PHP -> Perl ------------------------------------------- クラス パッケージ オブジェクト(インスタンス) データ構造 メソッド サブルーチン -------------------------------------------
コントローラーでサブルーチンの呼び出し
ようやく先週 Catalyst::Model::DBIC::Schemaでデータベースとの連携が取れて安心したのもつかの間。
コントローラー側で色々と詰まってました。。
CakePHPでは$this->method();で呼び出していた内容を
Catalystに移行する場合、ちょっと戸惑いました。
例)CakePHP
<?php class HogeController extends AppController{ function test(){ $this->test2(); } private function test2(){ echo 'Hello!'; } } ?>
上のようなメソッド間でやり取りするようなコードを設計する場合、Catalystには
forward,detach,visit,goと複数の手段があるのでどれを使うかで悩みました。
一旦下記に整理してみました。
forward[他のアクションに一部の処理をゆだねる]
sub forward_from :Local{ my($self,$c)=@_; my $result = $c->forward('/ctrl/flow/forward_to',[2,4]); #または・・ my $result = $c->forward('Catalll::Controller::Ctrl::Flow','forward_to',[2,4]); $c->response->body('AAA:'.$result->[0].'/BBB:'.$result->[1]); } sub forward_to :Private{ my($self,$c,$base,$height)=@_; return [$base * 2,$height * 3]; }
detach[他のアクションに処理を引き渡す(つまり呼び出し元に処理を戻さない)]
$c->detach('/hello/intro',['hoge','foo']); $c->detach('Catal::Controller::Hello','intro'); $c->detach();
visit[転送先から処理を返す(転送先の処理をあたかも新規のリクエストであるかのように振舞う)]
sub visit_from :Local{ my($self,$c)=@_; $c->visit('/ctrl/flow/visit_to'); } sub visit_to :Private{ my($self,$c)=@_; $c->response->body('正常動作中'); } sub begin :Private{ }
連鎖アクションの書き方
さて一緒に覚えた事として、画面遷移について
function top(){echo 'トップ';} -> function confirm(){echo '確認画面';} -> function execute(){echo '完了画面';}
という3連パターンがよくあるわけですが、これについてCatalystでは「連鎖アクション」で実装するそうです。
http://blog.livedoor.jp/sasata299/archives/51242968.html
試しにCakePHPで連鎖アクションと検索してみたのですが出てこなかったので、概念としては無いのでしょうか。
下記のような感じで連鎖アクションを記述することが可能です。
sub chain_top :Chained('/') :PathPart('first') :CaptureArgs(0) { my($self,$c)=_; $c->stash->{body}='TOPアクション'; } sub chain_second :Chained('chain_top') :PathPart('second') :CaptureArgs(1){ my($self,$c,$id)=_; $c->stash->{body} .= 'SECONDアクション:'.${id}; } sub chain_third :Chained('chain_second') :PathPart('third'){ my($self,$c)=_; $c->stash->{body} .= 'THIRDアクション'; $c->response->body($c->stash->{body}); }
呼び出し->
http://aaaaa:3000/first/second/108/third
属性の指定方法
http://d.hatena.ne.jp/Climber/20081007/1223349565
が参考になりました。
PathPart属性.....
Args属性.....エンドポイントで引数を制限する
PathPrefix属性.....
連鎖アクションを使うことで入力チェックなどができます
#memoを新規作成するためのアクション sub note_create :Chained('note_base') :PathPart('create') :Args(0){ my($self,$c)=@_; if($c->req->method eq 'POST'){ $c->forward('note_validate'); if(scalar@{$c->stash->{errors}}){$c->go('note_error');} } } sub note_edit :Chained('note_details') :PathPart('edit') :Args(0){ my($self,$c)=@_; if($c->req->method eq 'POST'){ $c->forward('note_validate'); if(scalar@{$c->stash->{errors}}){$c->go('note_error');} } } #検証用のプライベートアクション sub note_validate :Private{ my($self,$c)=@_; my $p = $c->request->body_params; my @errs; push @errs,'件名が空です。' unless $p->{title}; push @errs,'本文が空です。' unless $p->{body}; $c->stash->{erros} = \@errs; } #エラー発生時に呼び出さnote_error.ttでエラーを描画 sub note_error :Private{} ------- <html> [% FOREACH item = errors %] <li>[% item %]</li> [% END %] -------
Catalystでデバッグの仕方
PHPだとvar_dump();で済んだ所、catalyst(Perl)だと
ちょっと面倒っぽい。
スカラー値
use Data::Dumper; my $room_no = 1; $c->log->debug($room_no); --------- [debug]1 ---------
ハッシュ
use Data::Dumper; my %hash = (x=>1111,y=>222); $c->log->debug(\%hash); $c->log->debug(%hash); $c->log->debug($hash{x}); --------- [debug]1 --------- [debug] HASH(0x195451d8) [debug]y 222 x 1111 [debug] 1111
そんなわけで引き続き頑張ります。