SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Webアプリケーションフレームワーク「Catalyst」入門

初めてのCatalyst入門(5)
フロー制御とChainedアクション

アクションから別のアクションを呼び出す

  • X ポスト
  • このエントリーをはてなブックマークに追加

リダイレクト

 フロー制御ではアプリケーションに定義されているアクションなどを1回のリクエスト内で呼び出しますが、リクエストされたURLとは別のURLにリダイレクト(転送)させたい場合、例えばデータベースの項目削除後に一覧表示するURLに移動させる場合には、Catalyst::Responseに定義されているredirectメソッドを使用します。

 redirectメソッドは、引数として、リダイレクト先のURLHTTPステータスコード(3xx)の2つを指定します。ステータスコードは省略可能であり、省略時には302(Found)が設定されたものとして動作します。

 redirectメソッドは次のように使用します。

[リスト11]redirectメソッド呼び出し例
# 一時的なURLにリダイレクト
$c->res->redirect('http://example.com/temp/');
# ステータスコード301(Moved Permanently)を指定してリダイレクト
$c->res->redirect('http://new.example.com/', 301);
# アクションに対応するURIへリダイレクト
$c->res->redirect($c->uri_for('some_action'));

 ステータスコード301は、リクエストされたリソースが恒久的に移動されたことを意味します。例えばサイト移転後に古いURL「http://old.example.com/」にリクエストされた場合に、新しいURL「http://new.example.com/」へリダイレクトさせる際に使用します。

 ステータスコード302は、リクエストされたリソースが一時的に移動されていることを意味します。しかし掲示板などでPOSTで送信された後に、GETで一覧表示用URLに移動させるために使われるなどの、誤った使い方(もともとの仕様ではメソッドを変更してはならない)が多かったため、現在ではこのようなリダイレクトを行う場合には303(See Other)を使うべきです。

Chainedアクション

 最近のWebアプリケーションでは、リクエストパラメータとして値を渡すのではなく、URLのパスに値を含めた形式を採用する事例を多く見かけるようになってきています。

 例えば、IDが12である商品の34番目のコメントを表示する場合について、リクエストパラメータを使用した場合だと次のようになると思います。

http://<ホスト名またはIPアドレス><:Port>/comment?itemid=12&commentid=34

 これをパスに含めたURLに直すと次のようになります。

http://<ホスト名またはIPアドレス><:Port>/item/12/comment/34

 このようなURL(※注1)に対応するアクションは、:Regexアトリビュートを使用して定義することもできますが、コメントの編集や削除などのアクションを考えると、商品情報の取得やコメントの取得などの共通する部分などの似たような処理を繰り返し書く必要があり、メンテナンス性や可読性を下げる原因となります。

 Catalystでは、このような場合にChainedアクションを使用することで、パスの一部分に応じた処理を別々のアクションとして定義し、それらを連鎖(Chain)させることですっきりとしたコードを書くことができるようになっています。

 REST(Representational State Transfer)fulなURLと呼ばれます

Chainedアクションで使用するアトリビュート

 Chainedアクションでは、Chainedアトリビュートとともに、いくつかのアトリビュートを補助的に使用します。Chainedアクションで使用するアトリビュートには次のようなものがあります。

Chainedアクションで使用するアトリビュート
アトリビュート 説明
PathPart URLに現れる文字列を指定
Chained 対象アクションの前に呼び出されるアクションを指定
CaptureArgs 取り得る引数の数を指定。省略された場合にはエンドポイントとなる。
Args エンドポイントで取り得る引数の数を指定
PathPrefix PathPartの代わりにクラスのprefixを指定
ChainedParent 上位のコントローラの同名アクションに連鎖させるために指定
Chained/PathPart

 Chainedアクションを定義する場合の基本的な形は、「:Chained :PathPart:CatpureArgsまたは:Args)」となります。

 Chainedアトリビュートには上位となるアクション名を指定し、PathPartアトリビュートには、対象とするChainedアクションのパス文字列を指定します。

 URLの最上位となるChainedアクションには、Chainedアトリビュートの引数として「/」を指定します。:Chainedのように引数を持たない場合には、:Chained('/')を指定した場合と同じ意味になります。

 次の例では、「/foo/bar/baz」というURLにマッチするChainedアクションを定義しています。

[リスト12]Chained/PathPartアトリビュートの例
package MyApp::Controller::ChainedSample;

# 省略

# 最上位のアクションで、パス文字列はfooとなる
sub foo_action :Chained('/') :PathPart('foo') :CaptureArgs(0) {
  # 省略
}
# 上位のfoo_actionアクションを指定し、パス文字列はbarとなる
sub bar_action :Chained('foo_action') :PathPart('bar') :CaptureArgs(0) {
  # 省略
}
# 上位のbar_actionアクションを指定し、パス文字列はbazとなる
sub baz :Chained('bar_action') :PathPart :Args(0) {
  # 省略
}

 ここでは末端のbazアクションから、その上位アクションであるbar_actionアクション、bar_actionアクションから最上位のfoo_actionアクションを指定することで、連鎖するアクションを定義しています。ここで「/foo/bar/baz」のURLが呼び出された場合には、foo_actionbar_actionbazアクションの順に実行されます。

 Chainedアクションを定義するには、必ず最上位アクションにたどり着くようにする必要があることに注意してください。

 bazアクションではPathPartアトリビュートの引数を省略していますが、このように:PathPartと指定した場合や、:PathPart()と指定した場合、さらに:PathPart自体を省略した場合には、デフォルトの動作としてアクション名(サブルーチン名)が部分パス文字列に指定されたものとして動作します。

CaptureArgs/Args

 CaptureArgsArgsアトリビュートでは、対象となるアクションが取り得る引数の数を指定します。

 それぞれの違いは、対象とするアクションをエンドポイント(末端のアクション)とするかどうかになります。CaptureArgsを使用した場合にはエンドポイントにはならず、Argsアトリビュートを指定した場合、またはCaptureArgsArgsのどちらも指定しない場合にはエンドポイントになります。またCapturesArgsArgsのどちらも指定しない場合には、取り得る引数の数は不定(0以上)となります。

 ここで、次のようなChainedアクションを考えてみましょう。

[リスト13]CaptureArgs/Argsアトリビュートの例
package MyApp::Controller::ChainedSample;

# 省略

# 引数を1つだけ受け取る
sub capture_user :Chained('/') :PathPart('user') :CaptureArgs(1) {
  # 引数の値を受け取る
  my ( $self, $c, $userid ) = @_;
  # 省略
}
# CaptureArgs/Argsを省略しているのでエンドポイントとなる
sub address :Chained('capture_user') :PathPart('address') {
  # 省略
}
# 引数を1つも受け取らないエンドポイント
sub profile :Chained('capture_user') :PathPart('profile') :Args(0) {
  # 省略
}
# 引数を1つだけ受け取るエンドポイント
sub comment :Chained('capture_user') :PathPart('comment') :Args(1) {
  # 引数の値を受け取る
  my ( $self, $c, $commentid ) = @_;
  # 省略
}
# このアクションはどこからも呼び出されない
sub capture_blog :Chained('/') :PathPart('blog') :CaptureArgs(1) {
  # 省略
}

 このコードで構成されるパスは次のようになります。

CaptureArgs/Argsのサンプルで構成されるパス
パス エンドポイント エンドポイントで取り得る引数の数
/user/*/address/... address 不定(0以上)
/user/*/profile profile 0
/user/*/comment comment 1

 Catalystでは、エンドポイントからChainedアトリビュートの引数をたどりながら最上位まで到達したものだけをパスに割り当てます。よってcapture_blogアクションはエンドポイントからまったく参照されていないため、呼び出されることはありません。

 また、上記のコードでは指定された引数を@_から取得していますが、それ以外の方法としてCatalyst::Requestcaptures、およびargumentsから取得することもできます。

PathPrefix

 PathPrefixアトリビュートは、コントローラのネームスペースをパス文字列とする場合に指定します。PathPrefixPathPartの代わりとして指定するものなので、両方を同時に指定することはできません。

 次の例では、MyApp::Controller::Foo::BarコントローラのbazアクションのURLを、ネームスペースである「/foo/bar」として指定しています。

[リスト14]PathPrefixアトリビュートの例
package MyApp::Controller::Foo::Bar;

# 省略

# bazアクションのURLはネームスペース「/foo/bar」となる
sub baz :Chained('/') :PathPrefix {
  # 省略
}
ChainedParent

 ChainedParentアトリビュートは、親階層のコントローラに対して、同じ名前のアクションに連鎖させる場合に使用します。

 ここで、MyApp::Controller::Userコントローラと、その子階層のコントローラであるMyApp::Controller::User::PCMyApp::Controller::User::Mobileに同じ名前のprofileアクションを定義し、それぞれの子階層コントローラのprofileアクションにChainedParentアトリビュートを設定した場合について考えてみます。

[リスト15]ChainedParentアトリビュートの例
package MyApp::Controller::User;

sub profile :Chained('/') :PathPart('profile') :CaptureArgs(1) {
  #省略
}

package MyApp::Controller::User::PC;

sub profile :ChainedParent :PathPart('pc') :Args(0) {
  #省略
}

package MyApp::Controller::User::Mobile;

sub profile :ChainedParent :PathPart('mobile') :Args(0) {
  #省略
}

 上記のように定義すると、「/profile/*/pc」というURLが呼び出された場合には、UserUser::PCの順にprofileアクションが実行され、「/profile/*/mobile」というURLが呼び出された場合には、UserUser::Mobileの順にprofileアクションが実行されます。

次のページ
Chainedアクションのサンプル

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Webアプリケーションフレームワーク「Catalyst」入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 花田 善仁(ハナダ ヨシヒト)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/4626 2009/12/29 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング