例如:
我知道如何匹配 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 或 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 };
}
但这似乎不起作用;网址匹配,但$ bar_id始终为undef。如果我从正则表达式的末尾删除了可选的opperator,那么它会正确捕获$ bar_id,但是必须同时存在foo和bar才能获得url匹配。我不确定这是一个perl正则表达式问题,还是催化剂问题。有什么想法吗?
更新
Daxim指出,它是一个正则表达式问题。我不明白为什么上面的正则表达式不起作用,但我确实设法找到了一个:
sub foo : Regex('foo/([^/]+)(?:/bar/([^/]+))?') {
my ( $self, $c ) = @_;
my ( $foo_id, $bar_id ) = @{ $c->req->captures };
}
(我没有在像Daxim这样的捕获中使用\ d +,因为我的ID可能不是数字)
感谢大家的帮助和建议,我在Catalyst:D
中学到了很多关于处理网址的知识答案 0 :(得分:9)
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}){
# ...
}
}
请注意,@remainder
中的路径前缀和操作名称后面的所有剩余的网址段。此外,由于您没有指定所需的参数数量,因此Catalyst将允许没有任何args的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
}
答案 1 :(得分: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;