Smarty模板引擎(V5.3版)使用教程

<?php
declare(strict_types=1);

ini_set('display_errors', 'On');
ini_set('error_reporting', E_ALL);

const SMARTY_EXCEPTION_CATCH = 'Smarty\Exception: '; // 该字符串多次使用,故设置一个常量来保存以方便使用

require_once __DIR__ . '/smarty-5.3.0/libs/Smarty.class.php';

$smarty = new Smarty\Smarty();

// 设置几个重要目录(建议先手动创建好这些目录)
$smarty->setTemplateDir(__DIR__ . '/smarty/template');
$smarty->setConfigDir(__DIR__ . '/smarty/config');
$smarty->setCompileDir(__DIR__ . '/smarty/compile');
$smarty->setCacheDir(__DIR__ . '/smarty/cache');

// 检查Smarty所需目录(即上面四个目录)是否已创建
// $smarty->testInstall();
// exit;

$smarty->setLeftDelimiter('{MN:');
$smarty->setRightDelimiter('}');

$smarty->setEscapeHtml(true); // 对HTML启用自动转义

$smarty->caching = Smarty\Smarty::CACHING_LIFETIME_CURRENT; // 开启缓存(生产环境使用)
// $smarty->caching = Smarty\Smarty::CACHING_OFF; // 关闭缓存(开发环境使用)

$smarty->debugging = false; // 开启/关闭调试控制台


//========== 注册自定义行标签,标签名为“member” ==========//
// 自定义行标签使用示例
// --------------------------------------------------
// 姓名:{MN:member column="name"}
// 性别:{MN:member column="sex"}
// 出生:{MN:member column="birth"}
try {
    $smarty->registerPlugin(Smarty\Smarty::PLUGIN_FUNCTION, 'member',
        function (array $params): string {
            $column = strtolower((string)($params['column'] ?? '')); // column属性的值不区分大小写

            // 这里假设从数据库中查出来会员的记录
            $data = ['name' => '张三', 'sex' => '男', 'birth' => 2003];

            if ($column !== '') {
                $txt = (string)($data[$column] ?? '');
            } else {
                $txt = '';
            }

            return $txt;
        }
        , false);
} catch (Smarty\Exception $e) {
    exit(SMARTY_EXCEPTION_CATCH . $e->getMessage());
}
// 重要说明:$smarty->registerPlugin()方法的第四个参数$cacheable通常要设为false,否则会将标签的最终显示内容写死在缓存文件。


//========== 注册自定义块标签,标签名为“book” ==========//
// 自定义块标签使用示例
// --------------------------------------------------
// {MN:book limit="3"}
// 《[column:title]》 - [column:author]·著<br>
// {MN:/book}
try {
    $smarty->registerPlugin(Smarty\Smarty::PLUGIN_BLOCK, 'book',
        function (array $params, ?string $content, Smarty\Template $template, bool $repeat): string {
            if (is_string($content) && $content !== '' && !$repeat) {
                // 这里假设从数据库中查出来书籍的记录
                $rows = [
                    ['title' => '红楼梦', 'author' => '曹雪芹'],
                    ['title' => '西游记', 'author' => '吴承恩'],
                    ['title' => '水浒传', 'author' => '施耐庵'],
                    ['title' => '三国演义', 'author' => '罗贯中'],
                ];

                $useless = $template instanceof Smarty\Template;
                unset($useless);

                $limit = (int)($params['limit'] ?? 10); // 最多显示多少条记录
                $limit <= 0 && $limit = 10;

                $counter = 0;

                $html = '';
                foreach ($rows as $row) {
                    if ($counter === $limit) {
                        break;
                    }

                    // 替换占位符
                    $str = str_replace(
                        [
                            '[column:title]',
                            '[column:author]',
                        ],
                        [
                            $row['title'],
                            $row['author'],
                        ],
                        $content);

                    $html .= $str;

                    $counter++;
                }
            } else {
                $html = '';
            }

            return $html;
        }
        , false);
} catch (Smarty\Exception $e) {
    exit(SMARTY_EXCEPTION_CATCH . $e->getMessage());
}
// 重要说明
// 1、块标签会两次执行回调函数,分别是起始标记一次和结束标记一次,而开发者只需要在结束标记那次回调将最终内容返回即可。
//    判断是起始标记还是结束标记执行回调可以看$content和$repeat参数,起始标记执行回调时这两个参数分别是null和true,
//    而结束标记执行回调时这两个参数分别是标签体内容(string类型)和false。


$smarty->assign('title', '码农人生', true);
$smarty->assign('keywords', '码农,程序猿,IT民工', true);
$smarty->assign('description', '代码是早上写的,人是中午疯的。', true);
$smarty->assign('body', 'PHP是世界上最好の语言', true);
// 重要说明:$smarty->assign()方法的第三个参数$nocache通常要设为true,否则会将最终显示内容写死在缓存文件,这样对于某些内容会有问题,
//           例如用户名称,如果$nocache为false那么第一个用户访问页面后会将其用户名称写死在缓存文件,后面的用户访问页面也是显示第一个
//           用户的名称,通常来说只有那些长期不会变的内容(如站点名称)才能写死在缓存。

try {
    $smarty->display('default/demo.htm'); // 模板文件路径:__DIR__/smarty/template/default/demo.htm
} catch (Smarty\Exception $e) {
    exit(SMARTY_EXCEPTION_CATCH . $e->getMessage());
} catch (Exception $e) {
    exit('Exception: ' . $e->getMessage());
}



通过默认扩展的方式实现行标签

<?php
// 类文件:/smarty-5.3.0/src/FunctionHandler/User.php
declare(strict_types=1);

namespace Smarty\FunctionHandler;

use Smarty\Template;

/**
 * Smarty\FunctionHandler\User类
 */
class User extends Base
{
    /**
     * 构造方法
     */
    public function __construct()
    {
        $this->cacheable = false; // 禁止缓存该标签,相当于$smarty->registerPlugin()方法的第四个参数$cacheable
    }

    /**
     * 实现自定义行标签{MN:user}
     *
     * 重要说明
     * --------------------------------------------------
     * 必须在“Smarty\Extension\DefaultExtension::getFunctionHandler()”的switch语句追加case引入本标签,代码如下:
     * case 'user': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\User(); break;
     *
     * 自定义行标签使用示例
     * --------------------------------------------------
     * 姓名:{MN:user column="name"}
     * 性别:{MN:user column="sex"}
     * 出生:{MN:user column="birth"}
     *
     * @param mixed $params 标签属性(键值对)
     * @param Template $template Smarty\Template对象
     * @return string 标签输出内容
     */
    public function handle($params, Template $template): string
    {
        parent::handle($params, $template); // 调用父类handle()方法

        $column = strtolower((string)($params['column'] ?? '')); // column属性的值不区分大小写

        // 这里假设从数据库中查出来会员的记录
        $data = ['name' => '李四', 'sex' => '女', 'birth' => 2004];

        if ($column !== '') {
            $txt = (string)($data[$column] ?? '');
        } else {
            $txt = '';
        }

        return $txt;
    }
}



通过默认扩展的方式实现块标签

<?php
// 类文件:/smarty-5.3.0/src/BlockHandler/Novel.php
declare(strict_types=1);

namespace Smarty\BlockHandler;

use Smarty\Template;
use function is_string;

/**
 * Smarty\BlockHandler\Novel类
 */
class Novel implements BlockHandlerInterface
{
    /**
     * 是否缓存标签
     *
     * @return bool true=缓存|false=不缓存
     */
    public function isCacheable(): bool
    {
        return false; // 禁止缓存该标签,相当于$smarty->registerPlugin()方法的第四个参数$cacheable
    }

    /**
     * 实现自定义块标签{MN:novel}
     *
     * 重要说明
     * --------------------------------------------------
     * 必须在“Smarty\Extension\DefaultExtension::getBlockHandler()”的switch语句追加case引入本标签,代码如下:
     * case 'novel': $this->blockHandlers[$blockTagName] = new \Smarty\BlockHandler\Novel(); break;
     *
     * 自定义块标签使用示例
     * --------------------------------------------------
     * {MN:novel limit="3"}
     * 《[column:title]》 - [column:author]·著<br>
     * {MN:/novel}
     *
     * @param mixed $params 标签属性(键值对)
     * @param mixed $content 标签体内容(起始标记执行回调时为null,结束标记执行回调时为string)
     * @param Template $template Smarty\Template类实例
     * @param mixed $repeat 是否重复(起始标记执行回调时为true,结束标记执行回调时为false)
     * @return string 标签最终HTML代码
     */
    public function handle($params, $content, Template $template, &$repeat): string
    {
        if (is_string($content) && $content !== '' && !$repeat) {
            // 这里假设从数据库中查出来书籍的记录
            $rows = [
                ['title' => '红楼梦', 'author' => '曹雪芹'],
                ['title' => '西游记', 'author' => '吴承恩'],
                ['title' => '水浒传', 'author' => '施耐庵'],
                ['title' => '三国演义', 'author' => '罗贯中'],
            ];

            $useless = $template instanceof Template;
            unset($useless);

            $limit = (int)($params['limit'] ?? 10); // 最多显示多少条记录
            $limit <= 0 && $limit = 10;

            $counter = 0;

            $html = '';
            foreach ($rows as $row) {
                if ($counter === $limit) {
                    break;
                }

                // 替换占位符
                $str = str_replace(
                    [
                        '[column:title]',
                        '[column:author]',
                    ],
                    [
                        $row['title'],
                        $row['author'],
                    ],
                    $content);

                $html .= $str;

                $counter++;
            }
        } else {
            $html = '';
        }

        return $html;
    }
}



<!-- 模板文件:__DIR__/smarty/template/default/demo.htm -->
<!doctype html>
<html lang="zh">
<head>
    <meta charset="utf-8">
    <title>{MN:$title}</title>
    <meta name="keywords" content="{MN:$keywords}">
    <meta name="description" content="{MN:$description}">
</head>
<body>
{MN:$body}<br>
--------------------------------------------------<br>
姓名:{MN:member column="name"}<br>
性别:{MN:member column="sex"}<br>
出生:{MN:member column="birth"}<br>
--------------------------------------------------<br>
姓名:{MN:user column="name"}<br>
性别:{MN:user column="sex"}<br>
出生:{MN:user column="birth"}<br>
--------------------------------------------------<br>
{MN:book limit="3"}
《[column:title]》 - [column:author]·著<br>
{MN:/book}
--------------------------------------------------<br>
{MN:novel limit="2"}
《[column:title]》 - [column:author]·著<br>
{MN:/novel}
</body>
</html>

<!--

PHP是世界上最好の语言
--------------------------------------------------
姓名:张三
性别:男
出生:2003
--------------------------------------------------
姓名:李四
性别:女
出生:2004
--------------------------------------------------
《红楼梦》 - 曹雪芹·著
《西游记》 - 吴承恩·著
《水浒传》 - 施耐庵·著
--------------------------------------------------
《红楼梦》 - 曹雪芹·著
《西游记》 - 吴承恩·著

-->

Copyright © 2024 码农人生. All Rights Reserved