如何在Template Toolkit中删除变量?

4

看了一下模板工具包手册中的Template::Manual::VMethods部分,我没有看到可以实现此功能的方法。将undef赋值给变量也不起作用——之后variable.defined仍然返回true。

2个回答

2

好的,谷歌搜索"delete variable" site:mail.template-toolkit.org/pipermail/templates/找到了来自Felipe Gasper的问题[Templates] Can I “DELETE some_var”?,并得到了Petr Danihlik的两个答案。Petr建议:

[% SET foo = 1 %]
[% IF foo.defined %] defined1 [% END %]
[% PERL %]
delete($stash->{foo});
[% END %]
[% IF foo.defined %] defined2 [% END %]

有趣。当我们在TT模板中使用来自stash(Catalyst?)的引用时,我们会写[% var %]而不是[% stash.var %]。我在想你是否已经尝试过修改[% stash.var %] - Marco De Lellis
这样引用变量并没有带来任何新的可能性,是吗?我不能像我找到的答案中所示那样使用 PERL 指令,因为我使用的 TT 处理器不允许内联 Perl。 - Piotr Dobrogost

2
我看了一下Catalyst::View:TT 代码,以便了解变量上下文。
下面这个子程序是渲染工作的核心,我稍微总结了一下:
sub render {
    my ( $self, $c, $template, $args ) = @_;
    # [...]
    my $output;    # Template rendering will end here
    # Variables interpolated by TT process() are passed inside an hashref
    # as copies.
    my $vars = {
        ( ref $args eq 'HASH' ? %$args : %{ $c->stash() } ),
        $self->template_vars( $c )
    };
    # [...]
    unless ( $self->template->process( $template, $vars, \$output ) ) { 
        # [ ... ]
    }
    # [ ... ]
    return $output;
}

TT的process()函数使用$c->stash中变量的副本进行调用,那么我们为什么需要操作$c->stash来摆脱局部副本?也许我们不需要这样做。

此外,TT的define() VMethod和其他方法一样,似乎是为列表构建的。当对标量调用VMethod时,标量会自动提升为单个元素列表:也许出于这个原因,IF测试总是返回true。

我对带有指向DBIx::Class::ResultSet对象的引用的变量进行了一些测试,并且在变量测试时似乎可以正常工作:

[%- resultset_rs = undef %]
[%- IF ( resultset_rs ) %]
    <h3>defined</h3>
[%- END %]

第一行删除变量,第二行进行适当的测试。
更新:
如果您可以在 Catalyst 视图中的 config() 参数中添加 EVAL_PERL => 1 标志。
__PACKAGE__->config({
    # ...
    EVAL_PERL => 1
});

然后你可以在模板中使用 [% RAWPERL %] 指令,这将直接让你访问 Template::Context 对象:然后你可以删除变量,并且 .defined() VMethod 会做正确的事情。
[%- RAWPERL %]
    delete $context->stash->{ 'resultset_rs' };
[%- END %]
[%- IF ( resultset_rs.defined ) %]
    <h3>defined: [% resultset_rs %]<h3>
[%- ELSE %]
    <h3>undefined: [% resultset_rs %]<h3>
[%- END %]

你试图undef哪种类型的变量?是数组还是标量? - Marco De Lellis
它不起作用吗?你能否发布一部分代码,其中包含意外行为? - Marco De Lellis
它不能正常工作,因为它不测试一个变量是否被定义,而是测试它是否为真。我的变量表示像素大小,因此它可以具有值 0,在布尔上下文中为假。 - Piotr Dobrogost
文档中的指令/RAWPERL部分表示:模板工具包解析器读取源代码模板并将其作为输出生成Perl子程序的文本。 然后使用eval()将其评估为子程序引用。 除非我们在[% RAWPERL%]块中放置一些代码,否则可能会防止直接访问变量哈希引用。 - Marco De Lellis
你更新的代码与我回答中展示的代码有何不同? - Piotr Dobrogost
在手册中,你可以找到(小)区别的写法,其中写道[% RAWPERL %][% PERL %]更有效率:RAWPERL指令允许你编写直接集成到生成的Perl子例程文本中的Perl代码。它在编译时只被评估一次,并以缓存形式存储为编译后模板子例程的一部分。这使得RAWPERL块比PERL块更有效率。我认为你应该接受自己的答案,这是一个很好的机会去了解TT的内部结构。 - Marco De Lellis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接