3

嗨,我不想在控制器中重复相同的代码,所以我在主 MyApp 包中创建了一个子:

sub do_stuff {
    my $input = shift;

    do something
}

但后来我想在控制器中使用它MyApp::Controller::Foo

sub test : Chained('base') Args(0) {
    my ($self, $c) = @_;

    my $test = do_stuff($c->request->params->{s});

    do something more
}

我收到以下错误:

在 MyApp::Controller::Foo->test 中捕获异常“未定义的子例程 &MyApp::Controller::Foo::do_stuff 在 /home/student/workspace/MyApp/script/../lib/MyApp/Controller/Foo 调用。下午第 24 行,第 1000 行。”

我如何创建一个子程序/函数以在所有催化剂控制器中使用全局???

4

2 回答 2

4

原则上,它已经在您的 main 使用的所有模块中可用MyApp

但如果它是在主包中定义的,则必须从该命名空间(main或您的MyApp命名空间)中调用它,或者将其导入当前的包命名空间。

根据定义的位置,使用其中一种方式。

my $test = main::do_stuff($c->request->params->{s});
my $test = MyApp::do_stuff($c->request->params->{s});

另一种方法是将其导入每个包中的命名空间。

package MyApp::Controller::Foo;
if (defined &MyApp::do_stuff) {
  *do_stuff = *MyApp::do_stuff;
}

defined可以检查是否存在子程序。


另一方面,也许这个do_stuffsub 最好放在另一个具有Exporter的模块中。您可以在所有需要它的控制器或其他模块中使用它,Exporter 会自行将其导入您的命名空间。

于 2012-09-28T11:35:14.943 回答
1

在 Catalyst 中传递给大多数方法的上下文对象 ( $c) 已经是一个类型的对象MyApp,所以如果你说

$c->do_stuff($c->request->params->{s})

和调用一样

MyApp::do_stuff($c, $c->request->params->{s});

如果您希望全局子例程使用此上下文对象,那么您将需要考虑将它们编写为方法(即,包中的子例程,其中第一个参数始终是包的实例):

# to be called like   $c->do_stuff("s")  to do something with form input "s"
sub do_stuff {
    my ($c, $param) = @_;

    ... do something with $c->request->param($param) ...
}
于 2012-09-28T14:44:51.427 回答