如何在Mojolicious :: Lite应用程序中使用我自己的子程序(全局)

011*_*112 8 perl subroutine mojolicious mojolicious-lite

我需要能够在Mojolicious :: Lite应用程序中编写和调用我自己的子例程.但是,这样做的直观方式似乎并不奏效.我通过电子邮件发送了一位比我对此问题有更多Mojolicious经验的同事,他给我发了以下代码:

#!/usr/bin/env perl
use Mojolicious::Lite;

# Documentation browser under "/perldoc"
plugin 'PODRenderer';

get '/' => sub {
  my $self = shift;
  $self->render('index');
};

sub factorial {
    my $n = shift;
    return $n ? $n * factorial($n - 1) : 1;
}

app->start;
__DATA__

@@ index.html.ep
% layout 'default';
% title 'Welcome';
Welcome to the Mojolicious real-time web framework!

Five factorial: <%= main::factorial(5) %>

@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
  <head><title><%= title %></title></head>
  <body><%= content %></body>
</html>
Run Code Online (Sandbox Code Playgroud)

但是当我运行它时,它告诉我当我调用一个未定义的子程序时:

未定义的子程序&main :: factor在模块index.html.ep中从DATA第5行第32行调用.

我花了很多时间来研究这些代码,并尝试不同的东西来使它工作,但到目前为止唯一使它正常运行的是子程序是在@@ xxx.html的范围内定义的. EP的.我用Google搜索/搜索了stackoverflow中的"Mojolicious :: Lite中的用户定义子程序"和其他类似的查询.似乎没有出现任何事情.我对文档的搜索也证明是徒劳的.这似乎应该是一个简单的任务,但我有点卡住了.任何帮助,将不胜感激.

Joe*_*ger 6

正如PerC已经提到的,帮助程序是向模板添加行为(或访问行为)的首选机制.由于他已经展示了这个例子,我只想补充说你可以通过做这样的事情来混合两者(我正在删除pod渲染器插件,你不需要它).

#!/usr/bin/env perl
use Mojolicious::Lite;

get '/' => sub {
  my $self = shift;
  $self->render('index');
};

sub factorial {
    my $n = shift;
    return $n ? $n * factorial($n - 1) : 1;
}

helper factorial => sub { shift; factorial(@_) };

app->start;
__DATA__

@@ index.html.ep
% layout 'default';
% title 'Welcome';
Welcome to the Mojolicious real-time web framework!

Five factorial: <%= factorial(5) %>

@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
  <head><title><%= title %></title></head>
  <body><%= content %></body>
</html>
Run Code Online (Sandbox Code Playgroud)


Per*_*erC 5

如果您将sub重新编写为帮助程序,则可以从模板(或控制器)中访问它.

#!/usr/bin/env perl
use Mojolicious::Lite;

helper factorial => sub {
  my ($self, $n) = @_;
  return $n ? $n * $self->factorial($n - 1) : 1;
};

get '/' => 'index';

app->start;

__DATA__

@@ index.html.ep

Five factorial: <%= factorial(5) %>
Run Code Online (Sandbox Code Playgroud)

运行应用程序给出(减去日志记录):

$ perl app.pl get /
Five factorial: 120
$
Run Code Online (Sandbox Code Playgroud)

更新

这既不会回答你的问题,也会给你另一种选择.

我不知道你为什么喜欢从模板中调用main的sub.在我看来,模板(或我喜欢的视图)应该只呈现数据,而不是尝试计算/处理数据,这是模型(或控制器)的工作.由于控制器中的数据(和更多)在模板中可用,为什么不在控制器中调用sub并将结果传递给模板?结果可以是Perl数据结构,因此您不仅限于标量.

此外,当您将Mojolicious::Lite应用程序扩展为完整应用程序时,不再有用package main(它只是一个调用您的主应用程序的小应用程序package MyApp).这使得从模板调用泛型subs的整个想法更不用说前进了.

这是阶乘应用程序的另一个示例,其中计算在控制器中完成:

#!/usr/bin/env perl
use Mojolicious::Lite;

sub factorial {
  my $n = shift;
  return $n ? $n * factorial($n - 1) : 1;
}

get '/' => sub {
  my $self = shift;
  $self->render('index', result => factorial(5));
};

app->start;

__DATA__

@@ index.html.ep

Five factorial: <%= $result %>
Run Code Online (Sandbox Code Playgroud)