Катализатор: как объявить глобальную подпрограмму

Привет, я не хочу повторять один и тот же код в контроллерах, поэтому я создал подпрограмму в основном пакете 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. pm строка 24, строка 1000 ".

Как я могу создать подпрограмму / функцию для использования глобально во всех контроллерах Catalyst ???


person theguest    schedule 28.09.2012    source источник


Ответы (2)


В принципе, он уже доступен во всех модулях, которые использовались вашим основным 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_stuff подпрограмму лучше разместить в другом модуле, в котором есть Exporter. Вы можете использовать его во всех своих контроллерах или других модулях, где он вам нужен, а Exporter сам позаботится об его импорте в ваше пространство имен.

person simbabque    schedule 28.09.2012
comment
@theguest Отлично. :) Также добро пожаловать в SO. Примите ответ, нажав на галочку под голосами, если он решил вашу проблему. Вы также можете проголосовать за хорошие ответы, щелкнув стрелку, указывающую вверх. Если вам нужна помощь, см. часто задаваемые вопросы. - person simbabque; 28.09.2012

Объект контекста ($c), который вы передаете большинству методов в Catalyst, уже является объектом типа 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) ...
}
person mob    schedule 28.09.2012