# mier-template **Repository Path**: x_mier/mier-template ## Basic Information - **Project Name**: mier-template - **Description**: 轻量级、安全的 PHP 模板引擎,支持布局和自定义标签库 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-29 - **Last Updated**: 2026-01-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # mier Template Engine 轻量级、安全的 PHP 模板引擎,支持布局和自定义标签库。 ## 特性 - **轻量级**:无外部依赖,编译快速 - **安全**:内置 XSS 防护、敏感数据脱敏、PHP 代码安全检查 - **灵活**:支持自定义标签库、过滤器、布局 - **兼容**:适用于任何 PHP 框架,内置 Webman 适配器 - **协程安全**:支持 Swoole/Workerman 协程环境 ## 安装 ### 通过 Composer 安装 ```bash composer require mier/template ``` ### 本地开发 在 `composer.json` 中添加: ```json { "repositories": [ { "type": "path", "url": "./extend/orangeheart/template" } ], "require": { "mier/template": "*" } } ``` ## 快速开始 ```php use mier\Template\Engine; $engine = new Engine([ 'view_path' => '/path/to/templates', 'cache_path' => '/path/to/cache', 'layout_on' => true, 'debug' => true, ]); // 赋值变量 $engine->assign('title', 'Hello World'); $engine->assign(['user' => $user, 'list' => $items]); // 渲染模板 echo $engine->render('index/index'); ``` ## 模板语法 ### 变量输出 ```html {$name} {$user.name} {$name|default='Guest'} {$id ?? ''} {$user.name ?? 'Guest'} {$content|raw} {$name|upper} {$phone|mask_phone} {$list|implode=','} {$data|json_encode|default='[]'|raw} ``` ### 条件判断 ```html {if $user.role eq 'admin'}
管理员面板
{elseif $user.role eq 'user'}用户面板
{else}访客
{/if} {if isset $data}...{/if} {if empty $list}...{/if} {switch $user.role} {case 'admin'}管理员{/case} {case 'user'}普通用户{/case} {default}访客{/default} {/switch} {notempty name="$list"}列表有数据
{else}列表为空
{/notempty} {empty name="$list"}列表为空
{/empty} ``` ### 循环遍历 ```html {volist name="list" id="item"}{$user.name}
{/foreach} {foreach $config.items as $item}{$item.name}
{/foreach} {for start="1" end="10" name="i"} {$i} {/for} ``` ### $loop 变量 在 `{foreach}` 循环中,可以使用 `$loop` 变量获取循环状态信息: | 属性 | 说明 | |------|------| | `$loop.index` | 当前索引(从0开始) | | `$loop.iteration` | 当前迭代次数(从1开始) | | `$loop.first` | 是否是第一个元素 | | `$loop.last` | 是否是最后一个元素 | | `$loop.count` | 数组总数 | | `$loop.remaining` | 剩余元素数 | | `$loop.parent` | 嵌套循环时访问父级 loop | 示例: ```html {foreach $items as $item}分类 {$loop.parent.iteration} - 项目 {$loop.iteration}
{/foreach} {/foreach} ``` ### 函数调用 ```html {:url('index/index')} {:date('Y-m-d')} {:strtoupper($name)} ``` ### 模板包含 ```html {include file="header" /} {include file="common/sidebar" /} ``` ### 布局模板 在 `layout.html` 中: ```htmlHello, ' . $this->escape($name) . '!
'; } } ``` ### 使用标签库 ```php $engine->getCompiler()->registerTagLib('my', new MyTags()); ``` 在模板中: ```html {my:hello name="John" /} ``` ## 安全过滤器 | 过滤器 | 说明 | |--------|------| | `xss` | 基础 XSS 过滤 | | `xss_strict` | 严格 XSS(移除所有 HTML) | | `xss_clean` | XSS 过滤(保留允许的标签) | | `xss_rich` | 富文本 XSS 过滤 | | `mask_phone` | 手机号脱敏 | | `mask_email` | 邮箱脱敏 | | `mask_idcard` | 身份证脱敏 | | `mask_name` | 姓名脱敏 | | `safe_url` | URL 安全检查 | | `filter_sql` | SQL 关键字过滤 | 示例: ```html {$phone|mask_phone} {$email|mask_email} {$content|xss_rich} ``` ## 配置选项 | 选项 | 默认值 | 说明 | |------|--------|------| | `view_path` | `''` | 模板目录 | | `cache_path` | `''` | 缓存目录 | | `view_suffix` | `html` | 模板文件后缀 | | `cache_suffix` | `php` | 缓存文件后缀 | | `tpl_begin` | `{` | 左定界符 | | `tpl_end` | `}` | 右定界符 | | `layout_on` | `false` | 是否启用布局 | | `layout_name` | `layout` | 布局文件名 | | `layout_item` | `{__CONTENT__}` | 内容占位符 | | `taglib_pre_load` | `''` | 预加载标签库 | | `cache_enable` | `true` | 是否启用缓存 | | `debug` | `false` | 调试模式(每次都重新编译) | | `security_check` | `true` | 是否启用安全检查 | ## Webman 集成 1. 在 `config/view.php` 中配置: ```php return [ 'handler' => \mier\Template\Adapter\Webman\ViewHandler::class, 'options' => [ 'layout_on' => true, 'layout_name' => 'layout', 'taglib_pre_load' => \mier\Template\Tags\Form::class, ], ]; ``` 2. 在控制器中使用: ```php return view('index/index', ['title' => 'Hello']); ``` ## 协程安全 本模板引擎支持在 Swoole/Workerman 协程环境中安全使用。 ### 协程安全设计 | 组件 | 安全性 | 说明 | |------|:------:|------| | `ViewHandler::assign()` | ✅ | 变量存储在 `request()` 对象中,协程隔离 | | `ViewHandler::render()` | ✅ | 渲染后自动清理请求变量 | | `Engine::render($tpl, $vars)` | ✅ | 通过参数传递变量,无状态 | | `Engine::assign()` | ⚠️ | 修改实例属性,共享实例时不安全 | | `Compiler::compile()` | ✅ | 使用局部变量,无状态 | | `Security::*` | ✅ | 过滤方法无状态 | | `Security::setConfig()` | ⚠️ | 修改静态配置,只应在启动时调用 | ### 推荐使用方式 **通过 ViewHandler(推荐)** ```php // ✅ 协程安全:变量存储在 request 对象中 View::assign('title', '页面标题'); return view('index/home', ['data' => $data]); // ✅ 协程安全:直接传递所有变量 return view('index/home', [ 'title' => '页面标题', 'data' => $data ]); ``` **直接使用 Engine** ```php // ✅ 协程安全:通过参数传递变量 $engine = new Engine($config); echo $engine->render('template', [ 'title' => '页面标题', 'data' => $data ]); // ⚠️ 不推荐:共享实例时 assign 可能造成协程间数据污染 $engine->assign('key', 'value'); ``` ### 注意事项 1. **Security 配置**:`Security::setConfig()` 会修改全局静态配置,只应在应用启动时调用一次 2. **Engine 实例共享**:如果多个协程共享同一个 Engine 实例,避免使用 `assign()` 方法 3. **ViewHandler 适配器**:已做完整的协程安全处理,推荐在 Webman 中使用 ## 作者 - **橘子味的心** - x_mier@qq.com ## 许可证 MIT License