2010-12-10 56 views
1

例如:在Catalyst控制器中處理可選url參數的最佳方式是什麼?

我知道如何搭配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的建議下,我試圖用:正則表達式

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 regex問題還是Catalyst問題。有任何想法嗎?

更新:

由於Daxim指出,它的正則表達式的問題。我不明白爲什麼上述正則表達式不工作,但我還是設法找到一個不:

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

(我不喜歡Daxim沒有使用\ d +在捕捉我的ID可能爲數字),所有的幫助和建議

謝謝,我學到了很多在催化劑處理網址:d

回答

2

參見條款Catalyst::Manual::Intro#Action_types模式匹配(:Regex and :LocalRegex)


尼克寫道:

我不知道這是否是一個Perl的正則表達式的問題,或催化劑的問題。有任何想法嗎?

簡單地嘗試一下呢?

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; 
+0

感謝指針daxim,但我不能得到可選的正則表達式工作 - 我更新了與細節的問題。 – nick 2010-12-10 12:29:42

+0

是的,它是一個正則表達式問題 - 謝謝!我已經使用工作代碼更新了我的帖子。 – nick 2010-12-10 15:31:32

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}){ 
    # ... 
    } 
} 

記住路徑前綴和動作名稱後剩餘的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 
} 
+0

這也將匹配/ foo/123/baz/456這不是我想要的。 – nick 2010-12-10 13:49:00

+0

我已更新另一個選項。也許這更接近你要找的東西。 – 2010-12-10 14:12:53

+0

嗯,那也不完全是我在之後。我不想將foo_no_bar和foo_and_bar作爲單獨的函數處理,我只需要處理這兩種情況的一塊代碼。我想我可以有單獨的函數來捕獲參數,然後轉發到一個通用函數,但這似乎過於複雜。 – nick 2010-12-10 14:24:49

相關問題