接着上一篇,还是来说说 PHP 模板引擎 Smarty。PHP 的众多 CMS 框架,如 DEDE CMS,对于前端展示都是有一套自己开发的标签,用于显示管理后台维护的数据。在 DEDECMS 中,如下的代码

<h2>最近新闻</h2>
<ul>
    {dede:arclist typeid='1' row='10'}
    <li>[field:textlink/]</li>
    {/dede:arclist}
</ul>

就可以显示最近 type id 为 1 的 10 条新闻。在 Smarty 中创建属于自己的标签是很容易的,我之前在网络上搜索的关于创建 smarty 标签的内容大多数都是基于 Smarty2 的,我基于 Smarty3 中的 plugins 目录的代码了解到在 Smarty3 中创建自定义标签更为简单直观。

在 smarty 程序包的 plugins 目录中,可以看到有 block \ function \ modifier 等几种前缀的 php 文件。像 block 前缀的 php 文件可以创建闭合的标签,就如上文提到的那个 dede cms 新闻标签的例子。现在我正是要创建这样类型的标签。

我结合 CodeIgniter 来说明,我现在创建一个用户列表的标签,可以显示最近注册的用户。 在 smarty 的 plugins 目录中创建的文件会自动被 smarty 加载而识别的,文件名和其中的 function 名称需要特定的约定好的格式。 我现在想创建一个 users 标签,还有一个 limit 参数,用来显示取多少条数据

用户列表:
<ul>
    <{users limit='3'}>
        <li><{$user->login}></li>
    <{/users}>
</ul>

那么文件名就应该指定为 block.users.php,然后 function 应该命名为 smarty_block_users:

<?php
function smarty_block_users($params, $content, $smarty, &$repeat){
    if (empty($content)){
        if (empty($params['limit'])) {
            $limit = 10;
        } else {
            $limit = $params['limit'];
        }
        $CI =& get_instance();
        $GLOBALS['users'] = $CI->db->query("select * from users order by created_at desc limit $limit")->result();
    }
    if(isset($GLOBALS['users']) != NULL && count($GLOBALS['users'])>0){
        $user = array_shift($GLOBALS['users']);
        $smarty->assign('user', $user);
        if (count($GLOBALS['users']) == 0){
            unset($GLOBALS['users']);
            $repeat = false;
        }
        $repeat = true;
    }else {
        $repeat = false;
    }

    return $content;
}
?>

这个 function 中有四个参数,$params 参数存储的是标签中的属性信息,如上面的 limit。$content 是标签中间的内容,$smarty 是 smarty 的实例对象,$repeat 用于指定 block 是否重复执行。 解释完了 function 的参数,我想其中的执行原理应该很容易看明白了吧。