forwardとdetach
forward
とdetach
メソッドは、どちらも呼び出し先のアクションを実行しますが、それぞれの違いは、forward
メソッドが呼び出し元に処理が戻ってくるのに対して、detach
は呼び出し先アクション実行後に呼び出し元アクションには戻ってきません。また、forward
メソッドでは、呼び出し先アクションからの戻り値を受け取ることもできます。それぞれの用途として、forward
は、ある程度のまとまりを持ったデータを処理するために呼び出したり、入力値のチェックを行う場合などに使用します。
それに対してdetach
では、リクエスト処理を中断させることができるため、未ログインの場合にログインフォームにとばしたり、エラー発生時に独自のエラーページを表示させたりする場合などに使用します。
forwardとdetachメソッドの使い方
forward
とdetach
のメソッドは次のように引数を指定して呼び出します。
# (1)アクション名を指定 $c->forward('/foo/bar/baz'); $c->detach('/foo/bar/baz'); # (2)クラス、メソッド名を指定 $c->forward('MyApp::Controller::Foo::Bar', 'baz'); $c->detach('MyApp::Controller::Foo::Bar', 'baz'); # (3)なにも指定せず呼び出す(detachのみ) $c->detach();
(1)アクション名を指定
同じコントローラに属するアクションを呼び出す場合には$c->forward('do_action')
や$c->detach('do_action')
のようにアクション名だけを指定します。異なるコントローラのアクションを呼び出す場合には、この例のようにネームスペースを含めた形式で、スラッシュ(/
)から始まるアクション名を指定します。
また、$c->forward('/foo/bar/baz', [qw/aaa bbb ccc/])
のように、引数を配列として渡すことができます。この場合、呼び出し先からは$c->request->args
経由で引数を取得できます。detach
の場合も同様です。
(2)クラス、メソッド名を指定
アクションのクラス(モジュール)名とメソッド(サブルーチン)名を指定して呼び出すこともできます。メソッド名はアクションのメソッド名を指定する必要があります。例えばsub not_action {}
のようにアクションではないメソッドは指定することができません。
また、メソッド名を省略してクラス名だけを指定することもできます。例えば$c->forward('MyApp::View::TT')
のように呼び出すこともできますが、この場合に指定可能なクラスは、Catalyst::Component
を継承したクラスである必要があり、process()
メソッドが呼び出されます。クラス、メソッド名を指定する呼び出しの場合でも、アクション名を指定した場合と同様に、引数を配列として渡すことができます。
(3)何も指定せず呼び出す(detachのみ)
detach
では、3番目の例のように引数無しで呼び出すことができます。この場合には、直ちに処理チェーンを抜け出して、関連するend
アクションが呼び出されます。
visitとgo
forward
とdetach
メソッドでは別アクションのみを実行しますが、visit
とgo
アクションでは、begin
やauto
などの組み込みアクションが定義されている場合には、呼び出し先アクションが実行される前にこれらの組み込みアクションが呼び出されます。それぞれの違いは、visit
では呼び出し元アクションに処理が戻ってくるのに対して、go
では呼び出し先アクションの処理が終了した後に呼び出し元アクションに戻ってきません。
Catalyst::View::TT
を使用する場合では、アクションで明示的にテンプレート名が設定されていないと、デフォルトの動作として、実行されたアクションの「アクション名.tt」をテンプレートファイルとして扱います。forward
やdetach
では実行アクションは呼び出し元アクションになるため、呼び出し先テンプレートを使用する場合には明示的にテンプレートファイル名を設定する必要があります。visit
やgo
では実行アクションが呼び出し先アクションになるため、呼び出し先アクションのアクション名と同じ名前のテンプレートファイルを用意しておけば、明示的にテンプレートファイル名を設定する手間を省くことができます。
このことから、非常に多くのテンプレートファイルを使用する場合には、visit
/go
メソッドでアクションを呼び出すという決まりを作っておけば、アクション名とテンプレートファイル名の関係だけを管理すればよくなります。
visitとgoメソッドの使い方
visit
とgo
メソッドでは次のように引数を指定して呼び出します。forward
やdetach
メソッドではビューやモデルクラスを指定することもできましたが、visit
やgo
では、コントローラ以外を指定することはできません。
# (1)アクション名を指定 $c->visit('/foo/bar/baz'); $c->go('/foo/bar/baz'); # (2)コントローラのクラス、メソッド名を指定 $c->visit('MyApp::Controller::Foo::Bar', 'baz'); $c->go('MyApp::Controller::Foo::Bar', 'baz');
(1)アクション名を指定
アクション名の指定方法は、forward
やdetach
と同じです。この場合にも次のような形式で2種類の引数を渡すことができます。
my @captures = qw/aaa bbb ccc/; my @arguments = qw/ddd eee fff/; $c->visit('/foo/bar/baz', \@captures, \@arguments); $c->go('/foo/bar/baz', \@captures, \@arguments);
@captures
と@arguments
引数は、それぞれ呼び出し先からは$c->request->captures
、$c->request->args
経由でアクセスできます。
なお、ドキュメントでは\@captures
、\@arguments
の順番になっていますが、筆者が確認したところでは、この逆で指定する必要がありました。
(2)コントローラのクラス、メソッド名を指定
メソッド名を省略してクラス名だけを指定する場合には、visit
やgo
メソッドではコントローラだけを指定できます。この場合、コントローラクラスにはprocess()
メソッドを定義しておく必要があります。
また、クラス、メソッド名を指定する呼び出しの場合でも、アクション名を指定した場合と同様に、2種類の引数を配列として渡すことができます。