Mojolicious中如何向Helper代码引用统一传递参数?
Mojolicious Helper循环统一传参解决方案
问题场景还原
原来直接使用子例程引用时,可通过循环统一传递参数:
# 原工作正常的子例程写法 my @subs = (\&doit1, \&doit2); $_->("Hello") for @subs; sub doit1 { my $msg = shift; say $msg; } sub doit2 { my $msg = shift; say $msg; }
转为Helper后,直接调用代码引用会导致参数被忽略:
# 转为Helper后的问题写法 $app->helper(doit1 => sub { my $c = shift; my $msg = shift; say $msg; }); $app->helper(doit2 => sub { my $c = shift; my $msg = shift; say $msg; }); # 参数被忽略,因为Helper的代码引用第一个参数需要是控制器对象$c my @helpers = ($c->can('doit1'), $c->can('doit2')); $_->("Hello") for @helpers;
解决方案
Mojolicious Helper本质是绑定到控制器的方法,调用时必须传入控制器对象$c作为第一个参数,之后才是自定义参数。有三种实现方式:
方式1:直接通过控制器调用Helper名称
直接遍历Helper名称列表,用控制器对象调用并传入参数:
my @helper_names = qw(doit1 doit2); $c->$_("Hello") for @helper_names;
方式2:包装代码引用,绑定控制器对象
如果需要保留代码引用的调用方式,可以封装一层包装子例程,预先绑定$c:
my @wrappers = map { my $code = $c->can($_); sub { $code->($c, @_) } } qw(doit1 doit2); # 后续调用无需再传入$c,直接传自定义参数 $_->("Hello") for @wrappers;
方式3:直接传递控制器对象给代码引用
如果已经获取了Helper的代码引用,调用时把$c作为第一个参数传入即可:
my @helpers = ($c->can('doit1'), $c->can('doit2')); $_->($c, "Hello") for @helpers;
原理说明
Mojolicious Helper的代码引用默认第一个参数是控制器实例$c,这是方法调用的隐含要求。不管是通过$c->helper()语法还是直接调用代码引用,都必须满足这个参数结构,自定义参数要放在$c之后。
内容的提问来源于stack exchange,提问作者h q
相关产品推荐
相关产品推荐

