24 October 2005
This post may be outdated due to it was written on 2005. The links may be broken. The code may be not working anymore. Leave comments if needed.
今天用 Catalyst 写一个 RSS 聚合器程序的时候,发现 TT 的配置总是出错。后来才发现原来是配置选项出了点问题。

原来的代码差不多是这样子的:

package Feeder::V::TT;

use strict;
use base 'Catalyst::View::TT';
use Template::Constants qw( :debug );

__PACKAGE__->config({
   # any TT configurations items go here
   INCLUDE_PATH => Feeder->config->{'home'} . '/templates/',
   POST_CHOMP => 1,
   PRE_CHOMP => 1,
   EVAL_PERL => 1,
   PRE_PROCESS => 'header.tt',
   POST_PROCESS => 'footer.tt',
   DEBUG => DEBUG_PARSER | DEBUG_PROVIDER,
   CONTEXT => undef,

   # two optional config items
   CATALYST_VAR => 'Catalyst',
   TIMER => 1,
});

可怎么运行都不行。试了好一会儿,后来才发现原来 Template 的 INCLUDE_PATH 默认是用 : 来分隔多个路径的,比如:
INCLUDE_PATH => '/home/abw/templates:/usr/share/templates',
这样就是两个路径。而我运行在 Win32 下,发现 Template 将 E:/Fayland/Feeder/templates 划分为了两个路径 E 和 /Fayland/Feeder/templates, 所以运行程序总是跳出找不到模版文件。知道原因后查了查 Perl Template Toolkit 一书,在配置里加了一句:
DELIMITER    => ';',
这样就不是用 : 而是用 ; 来划分了。

这只是因为自己不熟悉 Template 的配置选项。于是就复习了一遍,将常用的几个翻译如下:

ABSOLUTE

指出用绝对路径的文件是否被解析。默认为 0.
如 /foo/bar 在 1 时为绝对路径而在 0 时为相对路径。
在 0 时使用类如 [% INSERT /etc/passwd %] 会出错,除非相对路径也有这文件。

ANYCASE

指示性关键字如 INCLUDE 是否允许小写

BLOCKS

此选项用于预先定义一系列模版块。
my $tt = Template->new({
BLOCKS => {
header => 'The Header. [% title %]',
footer => sub { return $some_output_text },
another => Template::Document->new({ ... }),
},
});
Hash 的值可以是模版内容,子程序或是 Template::Document
这样我们就可以在其他模版文件里调用它们。

COMPILE_DIR/COMPILE_EXT

Template 可以将模版文件编译成 Perl 文件保存以便接下来的再次调用。
my $tt1 = Template->new({
COMPILE_DIR => '/tmp/ttc',
COMPILE_EXT => '.ttc1',
});
COMPILE_DIR 是地址,COMPILE_EXT 为后缀名。

DELIMITER

这就是我所碰到的问题解决方案。解释见最前面。
# Win32 only
my $tt = Template->new({
DELIMITER => ';',
INCLUDE_PATH => 'C:/TT2/Templates;D:/My Templates',
});

CONSTANTS

编译时编译一次这些常量,而不是每次运行都编译一次。这样能稍微提高点速度。
my $tt = Template->new({
CONSTANTS => {
title => 'A Demo Page',
author => 'Joe Random Hacker',
version => 3.14,
},
};

CONSTANT_NAMESPACE

所有定义的 CONSTANTS 默认用 [% constants.title %] 来获得。而 CONSTANT_NAMESPACE 用来改变前缀。如:
CONSTANTS_NAMESPACE => 'const',
后,可以用 [% const.title %] 来访问。

NAMESPACE

用来定义多个 CONSTANT_NAMESPACE
my $tt = Template->new({
NAMESPACE => {
site => Template:::Namespace::Constants->new({
title => "Wardley's Widgets",
version => 2.718,
}),

author => Template:::Namespace::Constants->new({
name => 'Andy Wardley',
email => [email protected]',
}),
},
};

这样你就可以分别用 [% site.title %] 和 [% author.name %] 访问不同的常量。

CONTEXT

设置上下文。具体用途有点复杂。略过。

DEBUG

设置哪些地方需要调式。所定义的常量位于 use Template::Constants qw( :debug );
有两种写法:
DEBUG => DEBUG_PARSER | DEBUG_PROVIDER,
# or
DEBUG => 'parser, provider',
具体哪个啥意思查手册。

DEFAULT

当在 INCLUDE_PATH 里找不到模版文件时,默认调用该文件
my $tt = Template->new({
DEFAULT => 'notfound.html',
});

ERROR/ERRORS

定义一些常用的 错误 模版,然后在必要时调用它们。
my $tt = Template->new({
ERROR => {
'user.login' => 'user/login.html',
'user.passwd' => 'user/badpasswd.html',
'user' => 'user/index.html',
'default' => 'error/default',
},
});
必要时通过 [% THROW user.login 'no user id: please login' %] 来调用。
或在当前的 Template::Context 调用: $context->throw('user.passwd', 'Incorrect Password');
或在 Perl 代码中调用: die (Template::Exception->new('user.denied', 'Invalid User ID'));

EVAL_PERL

确定类如 PERL 或 RAWPERL 这样的块是否被执行。默认为 0

FILTERS

自定义自己的 filter, 过滤器。用于处理文件的某一些转换。 Template 默认自带了一些。
$tt = Template->new({
FILTERS => {
'sfilt1' => \&static_filter, # static
'sfilt2' => [ \&static_filter, 0 ], # same as above
'dfilt1' => [ \&dynamic_filter_factory, 1 ],
},
});
而后调用
[% FILTER sfilt1 %]
Blah blah blah.
[% END %]

INCLUDE_PATH

这个前面用了 n 多次了。它就是用于指定你要搜索的模版文件的文件夹。这几乎是用得最多的一个指令。

START_TAG/END_TAG

用以指定 template 指令的起始和终止符号。默认为 %
my $tt = Template->new({ 
START_TAG => quotemeta('<+'),
END_TAG => quotemeta('+>'),
});
这样就用 <+ INCLUDE foobar +> 而不是 [% %] 来调用指令了。

INTERPOLATE

内插。默认为 0
# INTERPOLATE => 0
<a href="http://[% server %]/[% help %]">
<img src="[% images %]/help.gif"></a>
[% myorg.name %]

# INTERPOLATE => 1
<a href="http://$server/$help">
<img src="$images/help.gif"></a>
$myorg.name
# explicit scoping with { }
<img src="$images/${icon.next}.gif">

OUTPUT/OUTPUT_PATH

这个我在老版本的 Eplanet 里是常用的。可以将内容输出到文件。

PRE_CHOMP, POST_CHOMP

是否在 [% %] 指令前后去除空行。默认不去除。这样的话:
<a href='[% address %]'>Click Here</a>
的话产生的最后结果可能是:
<a href='
fayland.html
'>Click Here</a>
我喜欢将它们设置成 1, 即使有时候应该分开的行也并起来了。

PRE_DEFINE, VARIABLES

这两个选项是一样的。用于设置一些默认值。如果 STASH 没有设置的话采用它们,设定的话忽略。
my $tt = Template->new({
PRE_DEFINE => {
title => 'A Demo Page',
author => 'Joe Random Hacker',
version => 3.14,
},
};

PRE_PROCESS, POST_PROCESS

调用一个 process 模版文件时预先调用和后来调用的模版文件。一般用于放置头文件和尾文件。
my $tt = Template->new({
PRE_PROCESS => [ 'config', 'header' ],
POST_PROCESS => 'footer',
};

STASH, process

这些在 Catalyst 没用到所以也不介绍了。

Enjoy!

Share me what u think.


blog comments powered by Disqus