2

例えば:

www.domain.com/foo/21と一致させる方法を知っています

sub foo : Path('/foo') Args(1) {
  my ( $self, $c, $foo_id ) = @_;
  # do stuff with foo
}

しかし、どうすればwww.domain.com/foo/21 OR www.domain.com/foo/21/bar/56に一致させることができますか?

sub foo : <?> {
  my ( $self, $c, $foo_id, $bar_id ) = @_;
  # do stuff with foo, and maybe do some things with bar if present
}

ありがとう

更新: Daxim の提案に従って、:Regex を使用しようとしました

sub foo : Regex('foo/(.+?)(?:/bar/(.+))?') {
   my ( $self, $c ) = @_;
   my ( $foo_id, $bar_id ) = @{ $c->req->captures };
}

しかし、これはうまくいかないようです。URL は一致しますが、$bar_id は常に undef です。正規表現の末尾からオプションの演算子を削除すると、$bar_id が正しくキャプチャされますが、url の一致を取得するには foo と bar の両方が存在する必要があります。これが perl regex の問題なのか、Catalyst の問題なのかはわかりません。何か案は?

アップデート:

Daxim が指摘しているように、これは正規表現の問題です。上記の正規表現が機能しない理由はわかりませんが、機能するものを見つけることができました:

sub foo : Regex('foo/([^/]+)(?:/bar/([^/]+))?') {
   my ( $self, $c ) = @_;
   my ( $foo_id, $bar_id ) = @{ $c->req->captures };
}

(IDが数値ではない可能性があるため、Daximのようにキャプチャで\ d +を使用しませんでした)

ヘルプと提案に感謝します。Catalyst での URL の処理について多くのことを学びました:D

4

2 に答える 2

10

属性は、特定の数の引数に制限する必要Argsはありませんたとえば、次のように動作するはずです。

sub foo :Args() {    # matches /foo, /foo/123, /foo/123/bar/456, /foo/123/bar/456/*
  my($self, $c, $foo_id, %optional_params) = @_;
  if($optional_params{bar}){
    # ...
  }
}

パス プレフィックスとアクション名の後の残りの URL セグメントはすべてに存在することに注意してください@remainder。また、必要な引数の数を指定していないため、Catalyst はこのアクションに一致する引数のない URL を許可します。それに応じて入力を検証してください。

UPDATED with :Chained example

次の (テストされていない) 触媒アクションは、探していると思われるもう少し厳密なアクション マッチングを提供します。欠点は、すべてのアクション間でデータを共有するために stash に依存しなければならないことです。

sub foo :Chained('/') :PathPart :CaptureArgs(1) {
  my($self, $c, $foo_id) = @_;
  $c->stash->{foo_id} = $foo_id; # or whatever
}

sub foo_no_bar :Chained('foo') :Args(0) {
  my($self, $c) = @_;
  # matches on /foo/123 but not /foo/123/bar/456
  my $foo_id = $c->stash->{foo_id}; 
}

sub bar :Chained('foo') :PathPart :Args(1) {
  my($self, $c, $bar_id) = @_;
  my $foo_id = $c->stash->{foo_id};
  # matches on /foo/123/bar/456 but not /foo/123 or /foo/123/baz/456
}
于 2010-12-10T12:40:45.033 に答える
2

Catalyst::Manual::Intro#Action_typesの項目Pattern-match(:Regex and :LocalRegex)を参照してください。


ニックは次のように書いています。

これが perl regex の問題なのか、Catalyst の問題なのかはわかりません。何か案は?

気軽に試してみてはいかがでしょうか。

repl>>> $_ = '/foo/21/bar/56'
/foo/21/bar/56

repl>>> m|foo/(\d+)(?:/bar/(\d+))?|
$VAR1 = 21;
$VAR2 = 56;

repl>>> $_ = '/foo/21'
/foo/21

repl>>> m|foo/(\d+)(?:/bar/(\d+))?|
$VAR1 = 21;
$VAR2 = undef;
于 2010-12-10T11:42:20.923 に答える