【问题标题】:Dealing with ambiguous controller actions in Perl Catalyst在 Perl Catalyst 中处理不明确的控制器操作
【发布时间】:2016-09-03 15:40:37
【问题描述】:

问题

我一直在学习 Catalyst Web 框架,并试图了解 Catalyst 如何将 URL 分派给应用程序“操作”。

看来我可以用模糊的 URL 调度规则编写我的应用程序:

package Myapp::Controller::Root {
    __PACKAGE__->config(namespace => '');
    ....
    sub foo :Local {
        my ( $self, $c ) = @_;

        $c->response->body('foo action in Root controller.');
    }
}

package Myapp::Controller::Foo {
    ....
    sub default :Path {
        my ( $self, $c ) = @_;

        $c->response->body('default action in Foo controller.');
    }
}

这两个动作在不同的包中定义,但都与“/foo/...”路径相关联。查看上面的代码,尚不清楚哪个操作将优先。启动应用程序时,Catalyst 似乎或多或少地随机做出该决定。有时是前者,有时是后者。

请注意,上面的代码是一个人为的示例,我可能不会故意创建两个映射到同一路径的不同操作。尽管如此,我不知道如何仅通过查看代码来预测最终会调用哪个操作。

问题

有没有办法指示 Catalyst 禁止这种歧义或至少提供警告?

【问题讨论】:

  • metacpan.org/pod/distribution/Catalyst-Runtime/lib/Catalyst/… 谈到了路由匹配,并表示如果同一控制器内有多个动作匹配同一路径,则代码中最后(最低)定义的动作将获胜。然而,它没有谈论几个控制器。按理说同样有效,但加载组件的顺序可能是随机的,因此您会看到波动。
  • 我建议在 irc.perl.org 上的 #catalyst 中提出这个问题。由于 Catalyst 的作者没有积极参与这里,它可能会在那里得到更好的答案。

标签: perl catalyst


【解决方案1】:

我不确定是否有官方的 Catalyst 方法可以做到这一点,但您可以尝试以下方法,从 Catalyst question on how to list all actions in an app 轻轻挖走

尝试在 App.pm__PACKAGE__->setup() 行之后添加类似以下内容:

# Start the application
__PACKAGE__->setup();

# Get all known actions and store the action name and source controller
my $controller_map = {};
my @controllers = map { __PACKAGE__->controller($_) } __PACKAGE__->controllers;
for my $controller ( @controllers ) {
    my $controller_name = ref $controller;
    my @actions = $controller->get_action_methods;
    for my $action ( @actions ) {
        my $name = $action->name;
        next if $name =~ m|^_|; # _DISPATCH, _BEGIN, _AUTO, _ACTION, _END
        next if $name eq 'auto';
        next if $name eq 'begin';
        next if $name eq 'index';
        $controller_map->{ $name }->{ $controller_name }++;
    }
}

# Show all action names that come from more than 1 controller
my $bad_action_names = 0;
for my $action ( sort keys %$controller_map ) {
    my @original_controllers = keys %{ $controller_map->{ $action } };
    if ( scalar @original_controllers > 1 ) {
        $bad_action_names++;
        print "Bad Action Names for '$action' : " . join(' ', @original_controllers) . "\n";
    }
}

die "Unable to continue!!!" if $bad_action_names;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多