Smarty 3.0.8
作者:Monte Ohrt<monte at ohert dot com>
作者:Uwe Tews
SMARTY 3 的介绍
3.0.5 发布公告:
现在,Smarty默认遵从PHP 的error_reporting级别。如果PHP没有遮盖E_NOTICE,而你尝试访问一个未设置的模板变量,你将看到一个E_NOTICE警告。 要恢复以前的习惯:
$smarty->error_reporting = E_ALL & ~E_NOTICE;
3.0 发布公告:
重要调整:RC4 and 3.0 版本之间做了一些API的调整。我们认为现在制作这些更好,而不是在3.0版本以后,立即批评3.1的API。在线文档已经更新来反映这些变化。具体如下:
---- RC4 -> 3.0 的API 变化----
$smarty->register->*
$smarty->unregister->*
$smarty->utility->*
$samrty->cache->*
所有变为local的方法调用如下:
$smarty->clearAllCache()
$smarty->registerFoo()
$smarty->unregisterFoo()
$smarty->testInstall()
等等。
function, block, compiler和 modifier plugins的注册已经统一成以下两个API调用:
$smarty->registerPlugin(...)
$smarty->unregisterPlugin(...)
pre, post, output 和 variable filters的注册已经统一成以下两个API调用:
$smarty->registerFilter(...)
$smarty->unregisterFilter(...)
请访问在线文档了解细节变化:
http://www.smarty.net/documentation
Smarty 3 API 已经对语法进行了重构,以适应程序的一致性和可组合性。Smarty 2 API语法仍然支持,但是会抛出一个废弃通知。你可以关闭这些通知,但是强烈建议调整你的语法到Smarty 3,因为Smarty 2 语法必须运行一个额外的rerouting wrapper(路径选择封套)。
基本上,所有Smarty方法遵循“fooBarBaz”驼峰式命名法。同样,所有Smarty属性现在都有getters 和 setters。举个例子,$smarty->cache_dir属性可以通过$smarty->setCacheDir('foo/')设置,通过$smarty->getCacheDir()得到。
一些Smarty 3 APIs的"is*"方法已经废弃,仅仅将其复制功能到现在使用的"get*"方法。
这里是Smarty 3 API的总结:
$smarty->fetch($template, $cache_id = null, $compile_id = null, $parent = null)
$smarty->display($template, $cache_id = null, $compile_id = null, $parent = null)
$smarty->isCached($template, $cache_id = null, $compile_id = null)
$smarty->createData($parent = null)
$smarty->createTemplate($template, $cache_id = null, $compile_id = null, $parent = null)
$smarty->enableSecurity()
$smarty->disableSecurity()
$smarty->setTemplateDir($template_dir)
$smarty->addTemplateDir($template_dir)
$smarty->templateExists($resource_name)
$smarty->loadPlugin($plugin_name, $check = true)
$smarty->loadFilter($type, $name)
$smarty->setExceptionHandler($handler)
$smarty->addPluginsDir($plugins_dir)
$smarty->getGlobal($varname = null)
$smarty->getRegisteredObject($name)
$smarty->getDebugTemplate()
$smarty->setDebugTemplate($tpl_name)
$smarty->assign($tpl_var, $value = null, $nocache = false)
$smarty->assignGlobal($varname, $value = null, $nocache = false)
$smarty->assignByRef($tpl_var, &$value, $nocache = false)
$smarty->append($tpl_var, $value = null, $merge = false, $nocache = false)
$smarty->appendByRef($tpl_var, &$value, $merge = false)
$smarty->clearAssign($tpl_var)
$smarty->clearAllAssign()
$smarty->configLoad($config_file, $sections = null)
$smarty->getVariable($variable, $_ptr = null, $search_parents = true, $error_enable = true)
$smarty->getConfigVariable($variable)
$smarty->getStreamVariable($variable)
$smarty->getConfigVars($varname = null)
$smarty->clearConfig($varname = null)
$smarty->getTemplateVars($varname = null, $_ptr = null, $search_parents = true)
$smarty->clearAllCache($exp_time = null, $type = null)
$smarty->clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
$smarty->registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = array())
$smarty->registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
$smarty->registerFilter($type, $function_name)
$smarty->registerResource($resource_type, $function_names)
$smarty->registerDefaultPluginHandler($function_name)
$smarty->registerDefaultTemplateHandler($function_name)
$smarty->unregisterPlugin($type, $tag)
$smarty->unregisterObject($object_name)
$smarty->unregisterFilter($type, $function_name)
$smarty->unregisterResource($resource_type)
$smarty->compileAllTemplates($extention = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)
$smarty->clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
$smarty->testInstall()
// 所有的getters/setters,适用于所有属性. 这里有一些:
$caching = $smarty->getCaching(); // get $smarty->caching
$smarty->setCaching(true); // set $smarty->caching
$smarty->setDeprecationNotices(false); // set $smarty->deprecation_notices
$smarty->setCacheId($id); // set $smarty->cache_id
$debugging = $smarty->getDebugging(); // get $smarty->debugging
文件结构
Smarty 3的文件结构和Smarty 2相似:
/libs/
Smarty.class.php
/libs/sysplugins/
internal.*
/libs/plugins/
function.mailto.php
modifier.escape.php
...
很多Smarty 3的核心功能位于sysplugins目录;在这里,你不需要改变任何文件。/libs/plugins/文件夹是Smarty放置插件的地方。你可以在这里添加你自己的东西,或者创建一个独立的插件目录,就和Smarty 2的一样。你还需要创建你自己的/cache/, /templates/, /templates_c/, /configs/文件夹。并确保/cache/和/templates_c/是可写的。
Smarty 3的典型的使用方式应该看起来很熟悉:
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->assign('foo','bar');
$smarty->display('index.tpl');
不管怎样,Smarty 3的内部运行方式完全不一样。Smarty 3大多数向后兼容Smarty 2,除了以下项目:
*)Smarty 3 只支持PHP5。在PHP4上不能运行。
*){php}标签默认不可用。通过$smarty->allow_php_tag=true设置为可用。
*)被空白包围的分隔符不再作为Smarty标签处理。因此, { foo }将不会编译为一个标签,你必须使用{foo}。这个变化使Javascript/CSS使用更加简单,消除了对{literal}的需求。通过$smarty->auto_literal = false设置为不可用;
*) Smarty 3 API有一点不同。很多Smarty 2 API调用废弃但仍可用。如果想要最大的效率,请把你的调用升级到Smarty 3。
Smarty 3有很多新的东西。这里有一些比较引人注目的项:
LEXER/PARSER(语法分析器)
Smarty 3现在使用lexing分词器作为他的语法分析器/编译器。基本上,这意味着Smarty添加的一些语法是生活更加简单,就像in-template math, shorter/intuitive函数参数选择,无限制的函数递归,更加精确的错误处理,等等。
WHAT IS NEW IN SMARTY TEMPLATE SYNTAX(SMARTY模板语法有什么新的东西)
Smarty 3 几乎在任何地方允许使用表达式。只要没有被安全策略,对象方法和属性等停用,表达式就可以包含PHP函数。{math}插件不在是必须的,但仍然支持BC。
例子:
{$x+$y} 将输出 x 和y的和.
{$foo = strlen($bar)} 函数用于赋值
{assign var=foo value= $x+$y} 用于属性
{$foo = myfunct( ($x+$y)*3 )} 作为函数参数
{$foo[$x+3]} 作为数组索引
Smarty标签可以在其他标签里作为值来使用。
例子:{$foo={counter}+3}
Smarty标签也可以用在双引号字符串中。
例子:{$foo="this is message {counter}"}
你可以在模板中定义数组。
例子:
{assign var=foo value=[1,2,3]}
{assign var=foo value=['y'=>'yellow','b'=>'blue']}
数组可以嵌套
{assign var=foo value=[1,[9,8],3]}
变量赋值有一个新的简短的语法。
例子:{$foo=$bar+2}
你可以将值赋给一个具体的数组元素。如果变量存在但不是一个数组,它将会在新值赋值之前转换为数组。
例子:
{$foo['bar']=1}
{$foo['bar']['blar']=1}
你可以向数组中追歼值。如果变量存在但不是数组,他将在新值赋值前转换为数组。
例子:{$foo[]=1}
你可以使用类PHP语法访问数组元素,同样也可以使用原来的“dot(点)”标记。
例子:
{$foo[1]} 普通访问
{$foo['bar']}
{$foo['bar'][1]}
{$foo[$x+$x]} 索引可以包含任何表达式
{$foo[$bar[1]]} 嵌套索引
{$foo[section_name]} smarty部分访问, 非数组访问!
保留了原来的“dot(点)”标记,并且有改进。
例子:
{$foo.a.b.c} => $foo['a']['b']['c']
{$foo.a.$b.c} => $foo['a'][$b]['c'] 使用变量索引
{$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c'] 用表达式作为索引
{$foo.a.{$b.c}} => $foo['a'][$b['c']] 使用嵌套索引
注意{ 和 } 用在嵌套的dot(点)语法时防止产生歧义。
变量名字本身可以是变量和包含表达式。
例子:
$foo 普通变量
$foo_{$bar} 变量名包含其他变量
$foo_{$x+$y} 变量名包含表达式
$foo_{$bar}_buh_{$blar} 变量名包含多个部分
{$foo_{$x}} 如果$x的值是1将输出变量
实现了对象方法链接。
例子: {$object->method1($x)->method2($y)}
循环中加入了{for}标签(代替了{section}标签):
{for $x=0, $y=count($foo); $x<$y; $x++} .... {/for}
在{for}标签的第一个开始的表达式里,任何数目的语句都可以用逗号隔开。
{for $x = $start to $end step $step} ... {/for}现在存在于SVN中。
你也可以
{for $x = $start to $end} ... {/for}
在这种情况下,步进值(step value)将根据起始值自动为1或者-1.
你可以用任何有效的表达式代替$start 和$end。
再循环内部如下特殊可以被访问:
$x@iteration = 迭代次数
$x@total = 总迭代数
$x@first = t第一次迭代为真
$x@last = 最后一次迭代为真
Smarty 2 {section} 语法仍然能支持。
更简短的 {foreach}语法循环一个数组。
例子:{foreach $myarray as $var}...{/foreach}
在foreach循环中,通过以下方式访问属性:
$var@key foreach $var数组键
$var@iteration foreach 当前迭代数 (1,2,3...)
$var@index foreach 当前索引数 (0,1,2...)
$var@total foreach $var 数组总数
$var@first 第一次迭代为真
$var@last 最后一次迭代为真
Smarty 2 {foreach}标签语法仍然支持。
注意: {$bar[foo]} 仍然表示一个存在于 {section} 中的名为foo变量。如果你要访问下标是foo的数组元素,你必须使用引号,例如{$bar['foo']},或者实用点语法{$bar.foo}.
While标签块现在已经实现:
{while $foo}...{/while}
{while $x lt 10}...{/while}
直接访问php函数:
你可以像直接访问修改器一样使用php函数,你现在可以直接访问php函数,前提是他们都有安全许可设置:
{time()}
{function}...{/function}实现了一个模板功能。这使他能够想一个插件一样重用代码序列。他可以递归的调用自己。模板函数必须使用新的标签{call name=foo...}调用。
例子:
模板文件:
{function name=menu level=0}
<ul class="level{$level}">
{foreach $data as $entry}
{if is_array($entry)}
<li>{$entry@key}</li>
{call name=menu data=$entry level=$level+1}
{else}
<li>{$entry}</li>
{/if}
{/foreach}
</ul>
{/function}
{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' =>
['item3-3-1','item3-3-2']],'item4']}
{call name=menu data=$menu}
输出生成:
* item1
* item2
* item3
o item3-1
o item3-2
o item3-3
+ item3-3-1
+ item3-3-2
* item4
函数标签自身必须含有“name”属性。这个名称是调用函数时的标签名。函数表钱可能含有多个附加的属性。这些是本地变量的默认设置。
新的{nocache}函数:
{nocache}...{/nocache}将声明一个模板section为无缓存。
例子:
{$foo nocache=true}
{$foo nocache} /*一样 */
{foo bar="baz" nocache=true}
{foo bar="baz" nocache} /*一样*/
{time() nocache=true}
{time() nocache} /* 一样 *
或者你也可以在脚本里将变量分配为无缓存:
$smarty->assign('foo',$something,true); //第三个参数是无缓存设置
{$foo} /* non-cached */
$smarty.current_dir 返回当前模板的目录名称。
你可以直接使用字符串作为模板的"string"类型。
例子:
$smarty->display('string:This is my template, {$foo}!'); // php
{include file="string:This is my template, {$foo}!"} // template
变量范围/变量存储
=================================
在 Smarty 2中, 所有赋值的变量都储存在Smarty的对象中。因此,php中所有赋值的变量被之后的所有获取和显示模板调用访问。
在Smarty 3中,我们选择将变量赋值到主Smarty对象,user-created 数据对象,和user-created模板对象。这些对象可以被链接。对像链末端可以访问所有属于那个模板的变量和所有父对象的变量。Smarty对象只能访问跟链接,但是一个链接可以从Smarty对象中独立出来。
所有已知的Smarty分配接口工作于数据和模板对象。
除了以上提到的对象,还有一个专门作为全局变量的存储空间。
一个Smarty数据对象可以像下面这样创建:
$data = $smarty->createData(); //创建根数据对象
$data->assign('foo','bar'); //像平常一样给变量赋值
$data->config_load('my.conf'); // 装载配置文件
$data= $smarty->createData($smarty); // 创建一个有一个Smarty对象父链接的数据对象
$data2= $smarty->createData($data); // 创建一个有$data数据对象父链接的数据对象
模板对象通过使用createTemplate方法创建。他同 fetch() 或display() 方法有着相同的参数分配。
函数定义:
function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null)
第一个参数可以是一个模板名称,一个smarty对象或者一个数据对象。
例子:
$tpl = $smarty->createTemplate('mytpl.tpl'); //创建没有父链接模板对象
$tpl->assign('foo','bar'); // 直接赋值变量
$tpl->config_load('my.conf'); // 加载配置文件
$tpl = $smarty->createTemplate('mytpl.tpl',$smarty); //创建有一个Smarty对象父链接的模板
$tpl = $smarty->createTemplate('mytpl.tpl',$data); // 创建有一个 $data对象父链接的模板
标准的etch() 和display()方法将隐式创建一个模板对象。如果在这些方法调用中没有特别指明$parent参数,模板对象将连接到Smarty对象作为他的父级。
如果一个模板通过 {include...}标签从另一个模板被调用,字幕版连回到调用的模板作为父级。
所有局部赋值的变量或者来自父模板的变量都是可访问的。如果模板通过使用{assign var=foo...} 或者{$foo=...}标签创建或修改一个变量,这些值仅仅局部可知(局部范围)。当模板存在,新变量或者修改的都不能在父模板看到。这和Smarty 2的行为一样。
使用Smarty 3,我们可以赋值变量时使用范围属性,它允许那些新变量或修改的全局可用(ie在父模板ie in the parent templates)。
可用的范围有局部,父级,根级和全局。
例子:
{assign var=foo value='bar'} // 没有具体指明范围,默认为 'local'
{$foo='bar'} // 同样, 局部范围
{assign var=foo value='bar' scope='local'} // 同样, 局部范围
{assign var=foo value='bar' scope='parent'} // 值在父对象可用
{$foo='bar' scope='parent'} // (通常是调用模板)
{assign var=foo value='bar' scope='root'} // 值将被输入到根对象
{$foo='bar' scope='root'} // 同一个根部下的所有模板可见.
{assign var=foo value='bar' scope='global'} // 值将输出到全局变量存储,
{$foo='bar' scope='global'} //对于任何其他模板可用.
范围属性也可以附加到{include...}标签。在这种情况下,具体的范围将作为所有引用模板内分配的默认范围。
插件
=======
Smarty3 保留了Smarty2一样的编码规则。区别是模板对象作为新增的第三个参数传递。
smarty_plugintype_name (array $params, object $smarty, object $template)
只要不用到特殊Smarty 2内核,Smarty 2插件仍然兼容。
模板继承
=====================
有了模板继承,你可以定义可以被子模板重写的区块,所以你的模板可以像这样:
parent.tpl:
<html>
<head>
<title>{block name='title'}My site name{/block}</title>
</head>
<body>
<h1>{block name='page-title'}Default page title{/block}</h1>
<div id="content">
{block name='content'}
Default content
{/block}
</div>
</body>
</html>
child.tpl:
{extends file='parent.tpl'}
{block name='title'}
Child title
{/block}
grandchild.tpl:
{extends file='child.tpl'}
{block name='title'}Home - {$smarty.block.parent}{/block}
{block name='page-title'}My home{/block}
{block name='content'}
{foreach $images as $img}
<img src="{$img.url}" alt="{$img.description}" />
{/foreach}
{/block}
我们在这里重定义所有区块,而在标题块我们使用{$smarty.block.parent},他告诉Smarty从父模板插入默认内容到他的位置。内容块被重写用来显示图片文件,而page-title被重写用来显示完全不同的文件。
如果我们提供grandchild.tpl,我们将得到:
<html>
<head>
<title>Home - Child title</title>
</head>
<body>
<h1>My home</h1>
<div id="content">
<img src="/example.jpg" alt="image" />
<img src="/example2.jpg" alt="image" />
<img src="/example3.jpg" alt="image" />
</div>
</body>
</html>
注意:在子模块所有位于 {extends} o或{block}标签之外的部分将被忽略。
继承树可以随着你的需求而变大(意味着你可以继承另外文件,另外的文件继承别的文件,一个接着继承一个),但是要提醒的是所偶有的文件在运行时要检测修改,因此继承越多系统开销越大。
那你可以使用如下方法代替在子模板中用{extends}标签定义 parent/child关系:
$smarty->display('extends:parent.tpl|child.tpl|grandchild.tpl');
子标签{block} 有追加或者预置属性可供选择。如此,父区块内容被追加或者预置于子区块的内容。
{block name='title' append} My title {/block}
Php 流
============
(查看在线文档)
静态类访问和命名空间支持
=========================================
你可以注册一个类,有可选的命名空间,在模板的用法是:
$smarty->register->templateClass('foo','name/name2/myclass');
在模板中你可以这样使用它:
{foo::method()} etc.
=======================
请浏览观看并发送任何问题/建议/等等 到论坛上。
http://www.phpinsider.com/smarty-forum/viewtopic.php?t=14168
Monte and Uwe