Каков наилучший способ передать необязательные аргументы URL в контроллере Catalyst? - PullRequest
1 голос
/ 10 декабря 2010

Например:

Я знаю, как сопоставить 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
}

Спасибо

Обновление: Следуя совету Даксима, я попытался использовать: 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.Есть идеи?

Обновление:

Как указывает Даксим, это проблема регулярных выражений.Я не понимаю, почему вышеприведенное регулярное выражение не работает, но мне удалось найти такое, которое работает:

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

(я не использовал \ d + в снимках, как Даксим, как мои идентификаторыможет не быть числовым)

Спасибо всем за помощь и предложения, я многое узнал об обработке URL в Catalyst: D

Ответы [ 2 ]

9 голосов
/ 10 декабря 2010

Атрибут 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
}
2 голосов
/ 10 декабря 2010

См. Элемент Сопоставление с образцом (: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;
...