11.8 自定义插件
Smarty 2.0版本引入了被广泛应用于自定义Smarty功能的插件机制。它包括如下类型。
(1)functions:函数插件。
(2)modifiers:修饰插件。
(3)block functions:区块函数插件。
(4)compiler functions:编译函数插件。
(5)prefilters:预滤器插件。
(6)postfilters:补滤器插件。
(7)outputfilters:输出过滤插件。
(8)resources:资源插件。
(9)inserts:嵌入插件。
为了与旧有方式保持向后兼容,除资源插件外,保留了通过register_* API方式装载函数的处理方法。如果不是使用API方式而是使用直接修改类变量$custom_funcs、$custom_mods等的方法,那么就需要修改程序了。或者使用API的方法,或者将自定义功能转换成插件。
插件总在需要的时候被装载。只有在模板脚本里调用的特定修饰、函数、资源插件等会被装载。此外,即便在同一个请求中有几个不同的Smarty实体运行,每个插件也只被装载一次。
预/补过滤器插件和输出过滤器插件的装载方式有些不同。由于在模板中未被提及,它们必须在模板被处理前通过API函数明确地装入系统。同类型的多个过滤器插件依据被装载的次序先后不同分别先后执行。
插件目录是包含一条路径信息的字符串或包含多条路径信息的字符串数组。安装插件的时候,将插件置于其中一个目录下,Smarty会自动识别使用。
11.8.1 插件的命名方式
插件文件和函数必须遵循特定的命名约定以便Smarty识别。
插件文件必须命名如下:
type.name.php
其中,type是如下插件中的一种。
(1)function;
(2)modifier;
(3)block;
(4)compiler;
(5)prefilter;
(6)postfilter;
(7)outputfilter;
(8)resource;
(9)insert。
name为仅包含字母、数字和下划线的合法标志符。例如:function.html_select_date.php、resource.db.php、modifier.spacify.php。
插件内的函数应遵循如下命名约定:
smarty_ type _ name ()
type和name的意义同上。如果指定的插件文件不存在或命名不合规范,Smarty会输出相应的错误信息。
11.8.2 插件的编写
Smarty可自动从文件系统装载插件,或者运行时通过register_* API函数装载。可以通过unregister_* API函数卸载已经装载的插件。
只在运行时装载的插件的函数名称不需要遵守命名约定。
如果某个插件依赖其他插件内的某些功能(例如某些插件功能捆绑于Smarty内),那么可以通过如下方法装载必需的插件。
require_once $smarty->_get_plugin_filepath('function', 'html_options');
Smarty对象通常作为传递给插件的最后一个参数(有两个例外:①修饰插件根本不接受传递过来的Smarty对象;②为了向上兼容老版本的Smarty,区块插件将&$repeat作为最后一个参数,因此Smarty对象是倒数第二个参数)。
11.8.3 函数插件
函数插件的编写语法格式如下。
void smarty_function_ name (array $params, object &$smarty)
模板传递给模板函数的所有的属性都包含在参数数组$params中,既可以通过如$params['start']的方式直接处理其中的值,也可以使用extract($params)的方式将所有值导入符号表中。
函数输出(返回值)的内容将取代模板中函数名称出现的位置(例如:fetch()函数)。同时函数也可能只是执行一些后台任务,并无任何输出。
如果函数需要向模板中增加变量或者使用Smarty提供的某些功能,可以通过$smarty对象实现。
例11-15 利用有输出插件函数随机输出数组内容。
<?php function smarty_function_eightball($params, &$smarty) { $answers = array('Yes', 'No', 'No way', 'Outlook not so good', 'Ask again soon', 'Maybe in your reality'); $result = array_rand($answers); return $answers[$result]; } ?>
在模板中调用方法如下。
Question: Will we ever have time travel? Answer: {eightball}.
例11-16 利用无输出插件函数给变量赋值。
<?php function smarty_function_assign($params, &$smarty) { extract($params); if (empty($var)) { $smarty->trigger_error("assign: missing 'var' parameter"); return; } if (!in_array('value', array_keys($params))) { $smarty->trigger_error("assign: missing 'value' parameter"); return; } $smarty->assign($var, $value); } ?>
11.8.4 修正器插件
修正器是一些短小的函数,这些函数被应用于模板中的一个变量,然后变量再显示或用于其他的一些文档。可以把修正器链接起来。其语法格式如下。
mixed smarty_modifier_ name (mixed $value, [mixed $param1,…])
修正器插件的第一个参数是不可缺少的。剩余的参数是可选的,它们的有无取决于期望执行哪一种操作。修正器必须有返回值。
例11-17 简单修正器插件实现字符串的替换。
这个插件主要目的是用另一个名字替换一个内置PHP函数的名字。它没有任何多余的参数。
<?php function smarty_modifier_capitalize($string) { return ucwords($string); } ?>
例11-18 更加复杂的修正器插件(实现字符串的拆分与替换)。
<?php function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_words = false) { if ($length == 0) return ''; if (strlen($string) > $length) { $length -= strlen($etc); $fragment = substr($string, 0, $length+1); if ($break_words) $fragment = substr($fragment, 0, -1); else $fragment = preg_replace('/\s+(\S+)?$/', '', $fragment); return $fragment.$etc; } else return $string; } ?>
11.8.5 块函数插件
块函数的定义语法如下。
void smarty_block_ name (array $params, mixed $content, object &$repeat)
块函数的语法格式为:{func} .. {/func}。其作用是用标记圈起一个块,然后对这个块的内容进行操作。
Smarty一般情况下调用两次用户函数:一次是在开始标记,另一次是在结束标记。块函数仅开始标记可以有属性。所有从模板传递给模板函数的属性包含在一个集合数组参数中。其值可以直接获取。例如,用$params['start']或者是用extract($params)将它们导入符号表中。
变量$content的值取决于是否因开始标记或结束标记调用用户函数。假如开始标记调用,则其值为空,如果是结束标记调用,其内容为模板块的内容。注意:模板块已经被Smarty处理,所以接收到的结果是输出后的模板而不是原样模板。
参数&$repeat通过参考引用传递给函数执行过程并为其提供一个可能值来控制显示块多少遍。默认情况下,在首次调用块函数(块开始标记)时变量$repeat值为true,在随后的所有块函数调用中其值为false。
例11-19 利用块函数对语句块进行注释。
<?php function smarty_block_translate($params, $content, &$smarty) { if (isset($content)) { $lang = $params['lang']; // do some intelligent translation thing here with $content return $translation; } }
11.8.6 输出过滤器插件
输出过滤器插件的作用是,在装载并执行完一个模板之后显示模板之前,操作该模板的输出。其定义语法格式如下。
string smarty_outputfilter_ name (string $template_output, object &$smarty)
输出过滤器函数第一个参数是需要处理的模板输出,第二个参数是调用这个插件的Smarty实例。此插件将会对参数进行处理并返回相应的结果。
例11-20 输出过滤器插件,根据E-mail地址阻止垃圾邮件。
function smarty_outputfilter_protect_email($output, &$smarty) { return preg_replace('!(\S+)@([a-zA-Z0-9\.\-]+\.([a-zA-Z]{2,3}|[0-9] {1,3}))!', '$1%40$2', $output); }