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/21www.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,但是 foo 和 bar 必须同时存在才能获得 url 匹配。我不确定这是 perl 正则表达式问题还是 Catalyst 问题。有任何想法吗?

更新:

正如 Daxim 指出的,这是一个正则表达式问题。我不明白为什么上面的正则表达式不起作用,但我确实设法找到了一个:

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

(我没有像 Daxim 那样在捕获中使用 \d+,因为我的 id 可能不是数字)

感谢大家的帮助和建议,我学到了很多关于在 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 来匹配此操作。相应地验证您的输入!

更新:链式示例

以下(未经测试的)催化剂动作将为您提供您似乎正在寻找的更严格的动作匹配。缺点是您必须依靠存储在所有操作之间共享数据。

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中的项目模式匹配(:Regex and :LocalRegex)


尼克写道:

我不确定这是 perl 正则表达式问题还是 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 回答