Category: Catalyst Keywords: Template Filters
昨日写了点 TT 内置过滤器(Template builtin Filters),现在有兴趣讲讲自己怎么写一个 filter.昨日说了 filter 分为两种:一种为静态,一种为动态。二者的区别是静态不接受任何参数,如 html, collapse, trim, ucfirst, lower 等,而动态接受参数,如 format('%0.3f'), indent("> ")而放置 filter 的地方也分为两种,一种是直接放在代码里,另一种是写为 Template::Plugin::Filter 的子类模块。
我打算先讲直接放在代码里的。
Static Filters
静态过滤器是最简单的。我们用个最简单的 filter 来写个 lower/ucfirst 过滤器。sub ucf {
my $text = shift;
$text = ucfirst lc $text;
return $text;
}
my $tt = Template->new({
FILTERS => {
'ucf' => \&ucf,
'lcf' => sub { lcfirst uc shift; },
},
});上面就是静态过滤器的两种形式。一种是 subroutine 子程序的引用,一种是匿名子程序。无论是哪种子程序都接受一个 shift 过来的字符串,然后返回一个 $string.
注册 filters 使用 FILTERS 参数。而 Catalyst 可以这么写:
package Eplanet::V::TT;use strict;而 filter 的应用与内置的是一样的。
use base 'Catalyst::View::TT';__PACKAGE__->config->{FILTERS} = {
'ucf' => \&ucf,
'lcf' => sub { lcfirst uc shift; },
};
[% FILTER ucf %]template is great[% END %]输出 Template is great
[% | lcf %]template is great[% END %]输出 tEMPLATE IS GREAT
Dynamic Filters
动态的是可以接受参数的。它的注册方法与静态的略微有点不同:my $tt = Template->new({
FILTERS => {
'ucf' => \&ucf, # our trusty static filter
'cut' => [ \&cut, 1 ], # our dynamic filter
},
});第一种是我们所熟悉的静态过滤器,而第二种就是动态过滤器。它传递的一个数组引用且第二个参数为 1.我们所熟悉的静态过滤器还有种写法:
'ucf' => [ \&ucf, 0 ],这与 'ucf' => \&ucf, 是一样的。动态过滤器所定义的子程序大致为这样子的:
sub cut {
my ($context, $len) = @_;
return sub {
my $text = shift;
$text = substr($text, 0, $len);
return $text;
}
}[% | cut(5) %]template is great[% END %]输出为 templ
动态过滤器里第一个参数 $context 是 Template::Context 的一个对象,这个涉及到 Template 的内核我也不太懂。
第二个参数 $len 这里就是 5.
它返回的必须是一个程序的引用。跟静态的差不多。不过这个返回的子程序引用是个闭包。这样我们差不多说清楚了 filter 怎么写了,下面说说怎么写一个模块。
Template::Plugin::Filter
package MyTemplate::Plugin::Filter::Textile;use strict;这是一个标准的写法:use base qw(Template::Plugin::Filter); see Template::Plugin::Filter
use Template::Plugin::Filter;
use base qw(Template::Plugin::Filter);
use Text::Textile;sub filter {
my ($self, $text) = @_;
$text = Text::Textile::textile($text);
return $text;
}1;
然后覆盖它的 filter 子程序。参数为 my ($self, $text) = @_; 返回字符串。一个静态过滤器。
而注册的写法为:
my $tt2 = Template->new({
PLUGIN_BASE => 'MyTemplate::Plugin::Filter'
PLUGINS => {
Textile => 'MyTemplate::Plugin::Filter::Textile',
},
});因为 Filter 是 Plugin 的一种,所以我们这里设置的是 PLUGINS.Catalyst 的 ::V::TT 写法类似:
__PACKAGE__->config->{PLUGIN_BASE} = 'MyTemplate::Plugin::Filter';
__PACKAGE__->config->{PLUGINS} = {
Textile => 'MyTemplate::Plugin::Filter::Textile',
};而实际用则这么写:[% USE Textile %]效果为:
[% FILTER $Textile %]this is _like_ *so* *cool*[% END %]
this is like so cool