rgamba / tonic
超快且强大的PHP模板引擎
Requires
- php: >=5.3.0
This package is not auto-updated.
Last update: 2024-09-28 17:54:29 UTC
README
超快且强大的模板引擎。纯PHP,无依赖。
用法
使用Tonic非常直接。
use Tonic\Tonic; $tpl = new Tonic("demo.html"); $tpl->user_role = "member"; echo $tpl->render();
它也非常灵活。上面的代码也可以写成这样
$tpl = new Tonic(); echo $tpl->load("demo.html")->assign("user_role","member")->render();
显示语法
使用Tonic
<body> <h1>Welcome {$user.name.capitalize().truncate(50)}</h1> User role: {$role.lower().if("admin","administrator").capitalize()} </body>
与纯PHP编写相比
<body> <h1>Welcome <?php echo (strlen($user["name"]) > 50 ? substr(ucwords($user["name"]),0,50)."..." : ucwords($user["name"])) ?></h1> User role: <?php if(strtolower($role) == "admin") { echo "Administrator" } else { echo ucwords($role) } ?> </body>
安装
使用composer安装
$ composer require rgamba/tonic
缓存
所有tonic模板都会编译回原生PHP代码。强烈建议您使用缓存功能,这样相同的模板就不需要反复编译,从而减少服务器端的CPU使用。
$tpl = new Tonic(); $tpl->cache_dir = "./cache/"; // Be sure this directory exists and has writing permissions $tpl->enable_content_cache = true; // Importante to set this to true!
修饰符
修饰符是各种方式修改输出变量的函数。所有修饰符都必须在变量之前,并且可以与其他修饰符链接。例如
{$variable.modifier1().modifier2().modifier3()}
我们也可以以相同的方式在关联数组中使用修饰符
{$my_array.item.sub_item.modifier1().modifier2().modifier3()}
处理日期
在Tonic模板中处理和格式化日期非常容易。
Tonic::$local_tz = 'America/New_york'; // Optionaly set the user's local tz $tpl = new Tonic(); $tpl->my_date = date_create();
并且模板
<p>Today is {$my_date.date("Y-m-d h:i a")}</p>
处理时区
<p>The local date is {$my_date.toLocal().date("Y-m-d h:i a")}</p>
这将把 $my_date
渲染为 Tonic::$local_tz
中配置的时区
自定义时区
<p>The local date is {$my_date.toTz("America/Mexico_city").date("Y-m-d h:i a")}</p>
修饰符列表
创建自定义修饰符
如果您需要自定义修饰符,可以扩展列表并创建自己的。
// This function will only prepend and append some text to the variable Tonic::extendModifier("myFunction",function($input, $prepend, $append = ""){ // $input will hold the current variable value, it's mandatory that your lambda // function has an input receiver, all other arguments are optional // We can perform input validations if(empty($prepend)) { throw new \Exception("prepend is required"); } return $prepend . $input . $append; });
然后您可以使用这个修饰符
<p>{$name.myFunction("hello "," goodbye")}</p>
匿名修饰符
有时您只需要在模板内部直接调用函数,这些函数的返回值是不断变化的,因此不能与静态变量链接。此外,它的值不依赖于任何变量。在这种情况下,您可以使用匿名修饰符。要做到这一点,您需要创建一个自定义修饰符,如果需要使用其他参数,请忽略 $input
参数。
Tonic::extendModifier("imagesDir", function($input){ // Note that $input will always be empty when called this modifier anonymously return "/var/www/" . $_SESSION["theme"] . "/images"; });
然后您可以直接从模板中调用它
<img src="{$.imagesDir()}/pic.jpg" />
上下文感知
Tonic阻止您在应用程序中逃避可能导致潜在攻击的变量。所有即将显示给用户的变量都应该被仔细转义,并且应该根据其上下文进行转义。例如,链接的href属性中的变量应该以不同的方式转义,而javascript标签或 <h1>
标签中的某些变量。好消息是,Tonic为您做了所有这些工作。
$tonic->assign("array",array("Name" => "Ricardo", "LastName", "Gamba")); $tonic->assign("ilegal_js","javascript: alert('Hello');");
并且HTML
<a href="{$ilegal_js}">Click me</a> <!-- Will render: <a href="javascript%3A+alert%28%27Hello%27%29%3B">Click me</a> --> <p>The ilegal js is: {$ilegal_js}</p> <!-- Will render: <p> The ilegal js is: javascript: alert('Hello');</p> --> <a href="?{$array}">Valid link generated</a> <!-- Will render: <a href="?Name=Ricardo&LastName=Gamba">Valid link generated</a> --> <p> We can also ignore the context awareness: {$ilegal_js.ignoreContext()}</p>
包含模板
您可以在另一个模板中包含一个模板
{include footer.html}
我们还可以获取外部页面并将其加载到当前模板中
{include http://mypage.com/static.html}
模板包含支持嵌套调用,但请注意,在模板“A”中包含模板“A”可能导致无限循环。
控制结构
如果 / 否则
制作条件非常简单
{if $user.role eq "admin"} <h1>Hello admin</h1> {elseif $user.role.upper() eq "MEMBER" or $user.role.upper() eq "CLIENT"} <h1>Hello member</h1> {else} <h1>Hello guest</h1> {endif}
您可以使用常规逻辑运算符(==, !=, >, <, >=, <=, ||, &&)或使用以下
循环
<ul> {loop $user in $users} <li>{$user.name.capitalize()}</h1> {endloop} </ul>
或者如果需要数组键
<ul> {loop $i,$user in $users} <li>{$i} - {$user.name.capitalize()}</h1> {endloop} </ul>
处理宏
if结构和循环构造可以以更HTML友好的方式编写,以便您的代码更易于阅读。以下是一个示例
<ul tn-if="$users"> <li tn-loop="$user in $users">Hello {$user}</li> </ul>
这完全等同于
{if $users} <ul> {loop $user in $users} <li>Hello {$user}</li> {endloop} </ul> {endif}
模板继承
Tonic支持单模板继承。其背后的理念是保持事物的简洁性。多重继承可能导致复杂的视图难以维护。
在Tonic中,模板继承基于块
。假设我们有以下基本模板
base.html
<html> <head> <title>Tonic</title> </head> <body> <section tn-block="header"> <h1>Default welcome message!</h1> </section> <section> <div tn-block="content"> <p>This is the default content.</p> </div> </section> <section tn-block="footer">Tonic 2016</section> </body>
然后你有几个部分模板或视图,并且你希望重用主base.html
作为“骨架”。为了做到这一点,我们使用块
。每个块由标签{block name}{endblock}
定义,或者由html属性tn-block="name"
定义,该属性将具有属性值的HTML元素实际封装为名为name的块。
inner.html
{ extends base.html } <section tn-block="header" class="myheader"> <h1>Welcome to my inner page!</h1> </section> <p>This content WON´T be rendered at all!</p> <div tn-block="content"> <p>This is the content of my inner view. </div>
结果,我们将得到以下视图
<html> <head> <title>Tonic</title> </head> <body> <section class="myheader"> <h1>Welcome to my inner page!</h1> </section> <section> <div> <p>This is the content of my inner view. </div> </section> <section>Tonic 2016</section> </body>
这里有几个关键字
{ extend }
标签。它唯一且必须的参数应该是相对于Tonic::$root
的模板文件(默认为./
)。tn-block="header"
html属性定义了块,并由HTML元素的闭合匹配标签封装。- 所有在子模板(inner.html)中找到的块将有效地替换父模板(base.html)上匹配的块。如果子模板中有一个块在父模板中没有定义,那么该块将完全不被渲染。
- 块名称必须是字母数字的,并且不得包含
$
或任何特殊字符或空格。 - 父模板(base.html)继承子模板(inner.html)的上下文(作用域、变量)。
- 你只能扩展1个模板。
注意也可以使用{block header}{endblock}
的表示法来定义块。我们更倾向于使用HTML属性,因为它更干净。例如
{block myBlock}<div><h1>Welcome</h1></div>{endblock}
与以下内容完全相同
<div tn-block="myBlock"><h1>Welcome</h1></div>
变更日志
- 2016-11-10 - 3.1.0 - 添加了对模板继承的支持
- 2015-03-25 - 3.0.0 - 添加了上下文感知和宏语法,用于条件语句和循环
- 2015-03-23 - 2.2.0 - 添加了命名空间支持,并添加了修饰符异常
- 2015-03-20 - 2.1.0 - 添加了扩展修饰符的选项
- 2015-03-19 - 2.0.0 - 重要更新。大多数结构的语法略有变化,与旧版本不兼容。