2012-09-28 19 views
3

喜repeate在控制器相同的代码,所以我创建主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 
} 

我得到以下错误:

Caught exception in MyApp::Controller::Foo->test "Undefined subroutine &MyApp::Controller::Foo::do_stuff called at /home/student/workspace/MyApp/script/../lib/MyApp/Controller/Foo.pm line 24, line 1000."

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

回答

4

原则上它已经在主MyApp使用的所有模块中可用。

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

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

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; 
} 

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


在另一方面,也许这do_stuff子是最好放在有Exporter另一个模块中。您可以在您需要的所有控制器或其他模块中使用它,Exporter将负责将其导入到您自己的名称空间中。

+0

非常感谢,现在有效。 – theguest

+0

@theguest太棒了。 :)另外,欢迎来到SO。如果它解决了您的问题,请点击投票下方的复选标记以接受答案。您也可以通过单击顶部指向箭头来提高答案。如果你需要帮助,请看[faq#howtoask]。 – simbabque

1

上下文对象传递给催化剂中的大多数方法($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) ... 
}