text / template
简单安全的字符串模板引擎(类似Twig语法),支持嵌套的if/elseif/else、循环、过滤器。简单的OOP API:仅一个类完成所有工作(2行代码)。快速安全:无代码生成,无eval()代码。通过回调扩展。全面测试。包含丰富的示例。
Requires
- php: >=5.4
- ext-pcre: *
Requires (Dev)
- nette/tester: *
- phpunit/phpcov: ^2.0
- satooshi/php-coveralls: *
README
{if user.searching=='template'}This is for you {= user.name }{else}Welcome {= user.name }{/if}
单类PHP5/7模板引擎,支持if/循环/过滤器
- 简单:无需编译或缓存 - 直接解析
input string
为output string
- 安全:无eval(); 无代码生成。无需文件系统访问。单元测试。
- 小巧:无依赖。
- 功能:嵌套循环、if/elseif/else、自定义过滤器、自动转义
旨在成为一个小型字符串模板引擎,以满足电子邮件或小型HTML模板的需求。它不打算替代像Smarty或Twig这样的预编译功能齐全的模板引擎。
TextTemplate使用正则表达式进行文本解析。不生成或评估代码 - 因此这可能是在非时间关键情况下的安全解决方案。
虽然大多数模板引擎依赖于评估生成的代码和文件系统访问,但Text-Template使用一组正则表达式来解析模板。既不生成任何中间代码,也不评估任何代码。因此,TextTemplate在设计上应该比Smarty或Twig更安全。
TextTemplate支持无限嵌套循环和序列。
基本示例
安装
// 1. Define the Template $tplStr = <<<EOT Hello World {= name } {if name == "Matthias"} Hallo {= name | capitalize } {elseif name == "Jan"} Hi Buddy {else} You are not Matthias {/if} EOT; // 2. Define the Data for the Template $data = [ "name" => "Matthias" ]; // 3. Parse $tt = new TextTemplate($tplStr); echo $tt->apply ($data);
我推荐使用 composer
灵活的标签开始/结束
composer require text/template
本文档引用默认标签:使用一个括号 {
作为开始,一个 }
作为结束分隔符。当然,它们是灵活的:如果你想更改这些,请参阅:TextTempate::setOpenCloseTagChars()
值注入
使用值标签
向代码中注入值。任何变量都将默认使用 htmlspecialchars()
编码。要输出原始内容,请使用 raw
过滤器:{=htmlCode|raw}
{= varName}
要访问数组元素或对象,请使用 "." 来访问子元素
循环
{= users.0.name}
您可以在其中插入循环
在每个循环内部,有两个魔法值 @index0
(索引从0开始)和 @index1
(索引从1开始)。
{for curName in names}
Current Name: {= curName}
{/for}
在循环内部,您可以 {break}
或 {continue}
循环。
{for curName in names}
Line {= @index1 }: {= curName}
{/for}
条件(if)
您可以使用if条件
快捷方式:测试变量是否为null
{if someVarName == "SomeValue"}
Hello World
{/if}
可以使用 &&(与)、||(或)和括号构建复杂逻辑表达式。
{if someVarName}
someVarName is set!
{/if}
{if !someVarName}
someVarName is not set!
{/if}
您可以在比较中使用的值上使用过滤器。
{if someVarName && otherVarName}
someVarName and otherVarName are set!
{/if}
{if someVarName || otherVarName}
someVarName or otherVarName are set!
{/if}
{if someVarName || (otherVarName && anotherVarName)}
Condition is true!
{/if}
{if someVarName && !(otherVarName && anotherVarName)}
Condition is true!
{/if}
您可以添加自定义运算符用于条件。
{if someArray|count > otherArray|count}
someArray has more items than otherArray
{/if}
添加运算符
您可以为条件添加自定义运算符。
添加新运算符
$tt->addOperator("contains", function ($operand1, $operand2) { return strpos($operand1, $operand2) !== false; } );
预定义运算符
条件(else)
{if someVarName == "SomeValue"}
Hello World
{else}
Goodbye World
{/if}
选择列表
{if someVarName == "SomeValue"}
Hello World
{elseif someVarName == "OtherValue"}
Hello Moon
{else}
Goodbye World
{/if}
调用函数
您可以注册用户定义的函数。
$template->addFunction("sayHello", function ($paramArr, $command, $context, $cmdParam, $self) { return "Hello " . $paramArr["msg"]; } );
调用函数并将输出放入模板
{sayHello msg="Joe"}
或将结果注入上下文进行进一步处理
{sayHello msg="Joe" > out}
{=out}
处理异常
使用 !>
捕获异常并将它们重定向到作用域。
{throw msg="SomeMsg" !> lastErr}
或使用 !break
或 !continue
来中断/继续循环
注释
使用 {# #}
添加注释(将从输出中删除
Template {# Some Comment #}
{# Some
Multiline
Comment #}
添加过滤器
您可以添加自定义过滤器或覆盖自己的过滤器。默认过滤器是html
(htmlspecialchars)。
添加新的过滤器
$tt->addFilter ("currency", function ($input, $decimals=2, $decSeparator=",", $thounsandsSeparator=".") { return number_format ($input, $decimals, $decSeparator, $thousandsSeparator); });
使用参数调用过滤器(参数分隔符为:
)
{= variable | currency:2:,:. }
在您的模板中使用此过滤器
{= someVariable | currency }
预定义过滤器
替换默认过滤器
默认情况下,出于安全考虑,所有值都将使用"DEFAULT"-过滤器进行转义。(除非在过滤器部分选择了"raw")
如果您出于某种原因想禁用此功能或更改转义函数,您可以覆盖DEFAULT-过滤器
$tt->addFilter ("_DEFAULT_", function ($input) { return strip_tags ($input); });
或者
$tt->setDefaultFilter("singleLine");
以下示例将用strip_tags()函数替换htmlspecialchars()转义器。
部分
部分就像函数一样,但提供它们包含的内容
{sectionxy name="someName"}
Some Content
{/sectionxy}
{sectionxy name="someName" > out}
Some Content
{/sectionxy}
{= out}
要使用部分,您只需设置回调
$textTemplate->addSection("sectionxy", function ($content, $params, $command, $context, $cmdParam, $self) { return "Content to replace section content with"; });
删除空行
{strip_empty_lines}
line1
line2
{/strip_empty_lines}
计数数组
{trim > countElem}{= var | count}{/trim}
{if countElem == "0" }
{/if}
函数返回重定向
将输出追加到变量中。
{print >> out}
A
{/print}
{print >> out}
B
{/print}
{= out}
参数调试
要查看传递给模板的所有参数,请使用
{= __CONTEXT__ | raw}
它将输出当前上下文的结构。
处理未定义变量
默认情况下,文本模板在模板尝试访问未定义变量时不会抛出任何异常。
为了提高调试,您可以通过将$softFail
设置为false
(apply()
函数的第二个参数)来切换此行为
try { $tt = new TextTemplate("{=someUndefinedName}"); echo $tt->apply([], false); // ^^^^^ } catch (UndefinedVariableExceptions $e) { echo "UndefinedVariable: {$e->getTriggerVarName()}" }
将返回
UndefinedVariable: someUndefinedName
更改标签开始和结束字符
有时在解析其他模板文件时,{tag}{\tag}
并不合适。您可以使用setOpenCloseTagChars()
函数更改开始和结束字符。
$textTemplate->setOpenCloseTagChars("{{", "}}");
上面的示例将监听{{tag}}{{/tag}}
。
基准测试
尽管解析器是用纯正则表达式构建的,但我尽量避免了像预读等过于昂贵的结构。
我们得到了相当好的结果
贡献、错误报告、增强
如果您想做出贡献,请发送您的Pull-Request或在github上打开一个问题。
- 错误 & 功能请求: GitHub Issues
保持测试为绿色:请参阅/提供单元测试。此项目使用nette/tester
进行单元测试。
此项目使用kickstart的基于docker的即用型开发容器。只需运行./kickstart.sh
即可运行此项目。
要启动开发容器
./kickstart.sh
要运行测试,请在容器内运行kick test
。(见.kick.yml
)
关于
Text-Template由Matthias Leuffen编写http://leuffen.de