<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0"><tr><th colspan="3" align="center">Smarty - the compiling PHP template engine</th></tr><tr><td width="25%" align="left" valign="bottom"><a href="smarty3.smarty2.bc.notes.html" accesskey="P">Prev</a></td><td width="50%" align="center" valign="bottom">Smarty3.0.x Installation Package</td><td width="25%" align="right" valign="bottom"><a href="list.html">Next</a></td></tr></table> # README[ 3.0.x使用指南] Smarty 3.0.8 Author: Monte Ohrt <monte at ohrt dot com > Author: Uwe Tews 泽注 | 因原英文章节太长,已去掉,只留翻译的文字。 | |-----| smarty3 说明 3.0.5版本发布说明: 现在smarty版本随着php默认error_reporting级别的发展进行改进,如果php(模版)未注明E_NOTICE,而你又试图使用一个未定义的变量,你将会得到一个E_NOTICE警告。如果不习惯这种改变可以设置回以前的模式: $smarty->error_reporting = E_ALL & ~E_NOTICE; 3.0发布说明: 一些API在由RC4(过渡)到3.0发布版时进行了调整。我们觉得现在作改变会比等3.0发布后再调整好,到3.1时必须立即放弃这些旧的API。在网上可以找到新手册,里面有关于两者不同的介绍。不同之处: ---API由RC4到3.0版的改变--- $smarty->register->* $smarty->unregister->* $smarty->utility->* $samrty->cache->* 上述API全部改为调用内置方法,例如: $smarty->clearAllCache() $smarty->registerFoo() $smarty->unregisterFoo() $smarty->testInstall() 等等 函数、块、编译器、插件调节器的注册、注销合并到由下面两个API调用: $smarty->registerPlugin(...) $smarty->unregisterPlugin(...) pre、post、output和变量过滤器的注册、注销合并到由下面两个API调用: $smarty->registerFilter(...) $smarty->unregisterFilter(...) 关于所有具体的变化,请参考在线手册 ---- 为了一致性和模块化,Smarty3的API已经重构了语法。仍然支持Smarty2 API语法,但会抛出一个过时提示。你可以屏蔽提示,不过严重推荐调整到Smarty3语法,因为Smarty2语法必须通过一个额外的包装器改道运行。 基本上,现在所有Smarty方法改用“fooBarBaz”式驼峰语法命名。同时,现在所有Smarty属性可取和可设,例如,$smarty->cache_dir属性可用$smarty->setCacheDir('foo/')设置,而且可用$smarty->getCacheDir()取回值。 一些Smarty3的API废除了诸如“is*”格式的方法,因为这些方法只是现在的“get*”方法的复制函数,所以没必要存在重复的方法/函数。 下面这些是Smarty3 API的大致纲要: <table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><p>$smarty-&gt;fetch($template, $cache_id = null, $compile_id = null, $parent = null)<br/> $smarty-&gt;display($template, $cache_id = null, $compile_id = null, $parent = null)<br/> $smarty-&gt;isCached($template, $cache_id = null, $compile_id = null)<br/> $smarty-&gt;createData($parent = null)<br/> $smarty-&gt;createTemplate($template, $cache_id = null, $compile_id = null, $parent = null)<br/> $smarty-&gt;enableSecurity()<br/> $smarty-&gt;disableSecurity()<br/> $smarty-&gt;setTemplateDir($template_dir)<br/> $smarty-&gt;addTemplateDir($template_dir)<br/> $smarty-&gt;templateExists($resource_name)<br/> $smarty-&gt;loadPlugin($plugin_name, $check = true)<br/> $smarty-&gt;loadFilter($type, $name)<br/> $smarty-&gt;setExceptionHandler($handler)<br/> $smarty-&gt;addPluginsDir($plugins_dir)<br/> $smarty-&gt;getGlobal($varname = null)<br/> $smarty-&gt;getRegisteredObject($name)<br/> $smarty-&gt;getDebugTemplate()<br/> $smarty-&gt;setDebugTemplate($tpl_name)<br/> $smarty-&gt;assign($tpl_var, $value = null, $nocache = false)<br/> $smarty-&gt;assignGlobal($varname, $value = null, $nocache = false)<br/> $smarty-&gt;assignByRef($tpl_var, &amp;$value, $nocache = false)<br/> $smarty-&gt;append($tpl_var, $value = null, $merge = false, $nocache = false)<br/> $smarty-&gt;appendByRef($tpl_var, &amp;$value, $merge = false)<br/> $smarty-&gt;clearAssign($tpl_var)<br/> $smarty-&gt;clearAllAssign()<br/> $smarty-&gt;configLoad($config_file, $sections = null)<br/> $smarty-&gt;getVariable($variable, $_ptr = null, $search_parents = true, $error_enable = true)<br/> $smarty-&gt;getConfigVariable($variable)<br/> $smarty-&gt;getStreamVariable($variable)<br/> $smarty-&gt;getConfigVars($varname = null)<br/> $smarty-&gt;clearConfig($varname = null)<br/> $smarty-&gt;getTemplateVars($varname = null, $_ptr = null, $search_parents = true)<br/> $smarty-&gt;clearAllCache($exp_time = null, $type = null)<br/> $smarty-&gt;clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)</p> <p>$smarty-&gt;registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = array())</p> <p>$smarty-&gt;registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())</p> <p>$smarty-&gt;registerFilter($type, $function_name)<br/> $smarty-&gt;registerResource($resource_type, $function_names)<br/> $smarty-&gt;registerDefaultPluginHandler($function_name)<br/> $smarty-&gt;registerDefaultTemplateHandler($function_name)</p> <p>$smarty-&gt;unregisterPlugin($type, $tag)<br/> $smarty-&gt;unregisterObject($object_name)<br/> $smarty-&gt;unregisterFilter($type, $function_name)<br/> $smarty-&gt;unregisterResource($resource_type)</p> <p>$smarty-&gt;compileAllTemplates($extention = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)<br/> $smarty-&gt;clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)<br/> $smarty-&gt;testInstall()</p> <p>//所有getters/setters,对所有属性有效,下面是一小部份:<br/> $caching = $smarty-&gt;getCaching(); // get $smarty-&gt;caching<br/> $smarty-&gt;setCaching(true); // set $smarty-&gt;caching<br/> $smarty-&gt;setDeprecationNotices(false); // set $smarty-&gt;deprecation_notices<br/> $smarty-&gt;setCacheId($id); // set $smarty-&gt;cache_id<br/> $debugging = $smarty-&gt;getDebugging(); // get $smarty-&gt;debugging</p> </td> </tr></table> 文件结构 Smarty3的文件结构与Smarty2非常相似: | ~~~ /libs/ Smarty.class.php /libs/sysplugins/ internal.* /libs/plugins/ function.mailto.php modifier.escape.php ... ~~~ | |-----| 很多Smarty3的核心功能位于sysplugins目录;你不必更改这里的文件。/libs/plugins/放置Smarty插件。你可以将自己的插件放进来,或者建立一个独立的插件目录,这些与Smarty2一样。你仍然需要建立自己的/cache/、/templates/、 /templates_c/、/configs/文件夹。确定/cache/和/templates_c/可写。 Smarty3的典型使用方式看起来应该也很熟悉: | ~~~ require('Smarty.class.php'); $smarty = new Smarty; $smarty->assign('foo','bar'); $smarty->display('index.tpl'); ~~~ | |-----| 然而,Smarty3内部的工作方式完全不同。Smarty3大部份向后兼容Smarty2,除了下面内容: *) Smarty3只适用于php5,不再支持php4。 *) [{php}](#)默认情况下关闭,如果确实需要可以设置$marty->allow_php_tag = true。 *) 分隔符内左右出现空格符时将不再当作Smarty标签对待,因此{ foo }会被Smarty忽略,但{foo}则可识别。这个改变是为javascript/css让路,但前述改变不包括必须用到的[{literal}](#),这个特性可用设置$smarty->auto_literal = false去掉。 *) Smarty3 API有点不同。大部份Smarty2 API已被弃用,但仍能工作。你应该升级到Smarty3,以发挥最大效能。 Smarty3有很多新事物,这里列下重要的清单: 语法分析/解析器 ============ Smarty3提供了一个语法分析器给解析器/编译器。从根本上说,这意味着Smarty有一些附加语法让工作更轻松,例如模板内计算、简写/直观函数参数选项、无穷函数递归、更多精确错误处理等等。 Smarty模板语法有什么新变化 ===================== Smarty3允许在任何地方放置表达式。表达式可以包含php函数,只要没有被安全策略、对象方法、对象属性等这些禁止。{math}插件不再是必须,但仍向前支持。 | ~~~ Examples:{$x+$y} 输出x、y的和{$foo = strlen($bar)} 表达式用在赋值函数{assign var=foo value= $x+$y} 表达式作为属性{$foo = myfunct( ($x+$y)*3 )} 作为函数参数{$foo[$x+3]} 作为数组索引 ~~~ | |-----| Smarty标签可以作为值包含进其它标签内。 | ~~~ Example: {$foo={counter}+3} ~~~ | |-----| Smarty标签同样可以用在双引号字符串内。 | ~~~ Example: {$foo="this is message {counter}"} ~~~ | |-----| 你可以在模板内定义数组。 | ~~~ Examples: {assign var=foo value=[1,2,3]} {assign var=foo value=['y'=>'yellow','b'=>'blue']} Arrays can be nested. 数组可以嵌套 {assign var=foo value=[1,[9,8],3]} ~~~ | |-----| 这是个分配变量(变量赋值)的新简写语法方式。 | ~~~ Example: {$foo=$bar+2} ~~~ | |-----| 可以为一个指定的数组元素赋值。如果变量存在但不是数组,那么在赋值之前将会自动转为数组。 | ~~~ Examples: {$foo['bar']=1} {$foo['bar']['blar']=1} ~~~ | |-----| 可以添加一个值到数组。如果变量存在但不是数组,那么在赋值之前将会自动转为数组。 | ~~~ Example: {$foo[]=1} ~~~ | |-----| 可以使用php式的语法访问数组元素,同样支持原始的dot(.)符号。 | ~~~ Examples:{$foo[1]} 普通访问形式{$foo['bar']}{$foo['bar'][1]}{$foo[$x+$x]} 下标(索引)可以包含任何表达式{$foo[$bar[1]]} 嵌套下标{$foo[section_name]} 访问Smarty配置文件的节块名,而不是访问数组! ~~~ | |-----| 保留原始的“.”符号,但有改进 | ~~~ Examples:{$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']] 用于嵌套索引 ~~~ | |-----| 注意当嵌套“.”索引时,“{”和“}”用于分清模棱两可、容易产生岐义的地址边界。 变量名本身可以是变量(类似php5中的可变变量)和可以包含表达式。 | ~~~ Examples:$foo 普通变量$foo_{$bar} 变量名包含其它变量 $foo_{$x+$y} 变量名包含表达式$foo_{$bar}_buh_{$blar} 多段变量名{$foo_{$x}} 如果$x值为1,则输出变量$foo_1。 ~~~ | |-----| 执行对象方法链 | ~~~ Example: {$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}用来求和。 同样可用: {for $x = $start to $end} ... {/for} 在这种情况下,step值会依start和end的值自动加1或减1。你也可以用表达式来替换$start和$end变量。在循环里面可以访问下面的这些特殊变量: $x@iteration = 迭代(循环)次数 $x@total = 总的迭代(循环、遍历)数 $x@first = 如果是第一个迭代则为true $x@last = 如果为最后一个迭代则为true Smarty2的{section}语法仍受支持。 新的短式{foreach}语法遍历数组。 | ~~~ Example: {foreach $myarray as $var}...{/foreach} ~~~ | |-----| 遍历循环里面,通过下列方式访问属性: $var@key 遍历$var数组键 $var@iteration 遍历当前迭代count (1,2,3...) $var@index 遍历当前索引count (0,1,2...) $var@total 遍历$var数组总数 $var@first 如果是第一个迭代则返回true $var@last 如果是最后一个迭代则返回true Smarty2{foreach}标签语法仍受支持。 注意 | {$bar[foo]}的意思仍然是名为foo的{section}里面的一个变量。如果你想通过索引foo访问数组元素,必须用引号,如{$bar['foo']},或者使用“.”语法{$bar.foo}。 | |-----| 这样执行while块标签: {while $foo}...{/while} {while $x lt 10}...{/while} 直接访问php函数: 正如你可以直接使用php函数作为调节器,你现在可以直接访问php函数,假如安全设置为允许的话: | ~~~ {time()} ~~~ | |-----| 现在有个新的{function}...{/function}块标签执行模板函数。它允许像插件函数一样重用代码序列。它可以调用自身递归。模板函数必须经由新的{call name=foo...}标签调用。 <table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><p>Example:</p> <p>Template file:<br/> {function name=menu level=0}<br/> &lt;ul class="level{$level}"&gt;<br/> {foreach $data as $entry}<br/> {if is_array($entry)}<br/> &lt;li&gt;{$entry@key}&lt;/li&gt;<br/> {call name=menu data=$entry level=$level+1}<br/> {else}<br/> &lt;li&gt;{$entry}&lt;/li&gt;<br/> {/if}<br/> {/foreach}<br/> &lt;/ul&gt;<br/> {/function}</p> <p>{$menu = ['item1','item2','item3' =&gt; ['item3-1','item3-2','item3-3' =&gt; ['item3-3-1','item3-3-2']],'item4']}</p> <p>{call name=menu data=$menu}<br/></p> <p>Generated output:<br/> * item1<br/> * item2<br/> * item3<br/> --o item3-1<br/> --o item3-2<br/> --o item3-3<br/> ----+ item3-3-1<br/> ----+ item3-3-2<br/> * item4</p> </td> </tr></table> 函数标签必须有“name”属性,调用函数时“name”为标签名。函数标签可以有若干附加属性。这些属性默认由局部变量设置。 新[{nocache}](#)块函数: 当模板启用缓存时,{nocache}...{/nocache}必须指明模板节块(section)不缓存。 新nocache属性: 你可以通过nocache属性指明变量/函数禁止输出缓存。 <table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><p>Examples:</p> <p>{$foo nocache=true}<br/> {$foo nocache} /* same */</p> <p>{foo bar="baz" nocache=true}<br/> {foo bar="baz" nocache} /* same */</p> <p>{time() nocache=true}<br/> {time() nocache} /* same */</p> </td> </tr></table> 或者你可以在脚本中像这样分配不缓存变量: $smarty->assign('foo',$something,true); //第三个参数为nocache设置 [$smarty.current_dir](#)返回当前模板目录名。 你可以通过“string”[资源](#)类型使用直接字符串作为模板。 | ~~~ Examples:$smarty->display('string:This is my template, {$foo}!'); // php{include file="string:This is my template, {$foo}!"} // template ~~~ | |-----| 变量作用域 / 变量贮存 ================ 在Smarty2中,所有赋值变量全部贮存在Smarty对象里面。因此,所有在php里面分配的变量是后面通过调用fetch和display模板来访问的。 在smarty3中,我们可以选择分配变量给主Smarty对象、自建数据对象和自建模板对象,这些对象支持链式。这些对象在链的末尾可以访问所有模板变量和父对象里面的所有变量。 Smarty对象只能作为链的根,但链可以从Smarty对象中分离出来。 所有已知Smarty分配接口将作用于数据和模板对象。 除此之外,上述对象同时还是个特殊的全局变量存区。 可像下面一样建立一个Smarty数据对象: <table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><p>$data = $smarty-&gt;createData(); // 建立根数据对象<br/> $data-&gt;assign('foo','bar'); // 像平常一样分配变量<br/> $data-&gt;config_load('my.conf'); // 加载配置文件</p> <p>$data= $smarty-&gt;createData($smarty); // 建立一个有父对象的数据对象,该父对象为Smarty对象</p> <p>$data2= $smarty-&gt;createData($data); // 建立一个有父对象的数据对象,该父对象为$data数据对象</p></td> </tr></table> 可以使用createTemplate方法建立模板对象。它有与[fetch()](#)或[display()](#)方法一样的分配参数。 函数定义: function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null) 第一个参数可以是模板名、Smarty对象或数据对象。 <table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><p>Examples:<br/> $tpl = $smarty-&gt;createTemplate('mytpl.tpl'); // 建立一个不用$parent的模板对象<br/> $tpl-&gt;assign('foo','bar'); // 直接分配变量<br/> $tpl-&gt;config_load('my.conf'); // 加载配置文件</p> <p>$tpl = $smarty-&gt;createTemplate('mytpl.tpl',$smarty); // 建立模板,带parent,链至Smarty对象<br/> $tpl = $smarty-&gt;createTemplate('mytpl.tpl',$data); // 建立模板,带parent,链至$data对象</p></td> </tr></table> 标准的fetch()和display()方法会暗中建立一个模板对象。如果$parent参数没有在这些方法调用中指明,那么模板对象会链回Smarty对象作为parent。如果模板被另一个模板通过{include...}标签调用,那么子模板链回调用它的模板作为parent。 可访问所有局部变量或父模板变量。如果模板通过使用{assign var=foo...}或{$foo=...}标签建立或修改一个变量,这些新变量也只有局部作用域。当退出模板时,新变量或修改后的变量在父模板中不可见。在Smarty2中具有同样行为。 (不过在)在Smarty3中我们(多了件武器),可以通过*scope*属性分配变量,这样就允许这些新变量或修改后的变量具有全局作用域的可访问性(如在父模板中可见)。 scopes的可能值为*local*、*parent*、*root*和*global*。 <table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><p>Examples:<br/> {assign var=foo value='bar'} // 没有指定scope,默认为‘local’<br/> {$foo='bar'} // 同上<br/> {assign var=foo value='bar' scope='local'} // 同上,local作用域</p> <p>{assign var=foo value='bar' scope='parent'} // 父模板可以访问该值<br/> {$foo='bar' scope='parent'} // (普通的调用模板)</p> <p>{assign var=foo value='bar' scope='root'} // 值将输出到根对象,<br/> {$foo='bar' scope='root'} // 因此该值在使用同一根的所有模板中可见</p> <p>{assign var=foo value='bar' scope='global'} // 值将输送至全局变量存区<br/> {$foo='bar' scope='global'} // 这些值在任何、所有模板中可见</p></td> </tr></table> scope属性同样可附加至[{include...}](#)标签中。在这种情况下,指定scope则指定包含模板里面所有已分配变量具有同样作用域。 插件 === Smarty3使用与Smarty2一样的编码规则。不同之处在于前者将模板对象作为第三个参数传递(到插件)。 smarty_plugintype_name (array $params, object $smarty, object $template) 仍然兼容Smarty2插件,只要这些插件没有使用特殊的Smarty2内部结构。 模板继承: ======= 通过模板继承你可以定义块,这些块区域可被子模板覆盖,因此,你的模板可以这样做: <table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><p>parent.tpl:<br/> &lt;html&gt;<br/> &lt;head&gt;<br/> &lt;title&gt;{block name='title'}My site name{/block}&lt;/title&gt;<br/> &lt;/head&gt;<br/> &lt;body&gt;<br/> &lt;h1&gt;{block name='page-title'}Default page title{/block}&lt;/h1&gt;<br/> &lt;div id="content"&gt;<br/> {block name='content'}<br/> Default content<br/> {/block}<br/> &lt;/div&gt;<br/> &lt;/body&gt;<br/> &lt;/html&gt;</p> <p>child.tpl:<br/> {extends file='parent.tpl'} <br/> {block name='title'}<br/> Child title<br/> {/block}</p> <p>grandchild.tpl:<br/> {extends file='child.tpl'} <br/> {block name='title'}Home - {$smarty.block.parent}{/block} <br/> {block name='page-title'}My home{/block}<br/> {block name='content'}<br/> {foreach $images as $img}<br/> &lt;img src="{$img.url}" alt="{$img.description}" /&gt;<br/> {/foreach}<br/> {/block}</p></td> </tr></table> 我们在这里重定义了所有块,然而,在标题块方面我们用了[{$smarty.block.parent}](#),它告诉Smarty,在这块地方插入取自父模板的默认内容。内容块被显示的图像文件覆盖,同时,页面标题同样被不同的标题所覆盖。 如果渲染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}或{block}标签节块外的所有内容被忽略。 | |-----| 继承树大小没有规定,只要你愿意你想搞多大都可以(意为你继承的文件上面有个父文件,父文件上面可以有个爷文件,爷文件上面有个曾祖父文件...生生不息无穷尽),但需要注意所有文件都必须在运行时检查修改设置,更多的继承意味着更大的开销。 不用在子模板文件中使用{extends}标签定义parent/child关系,你可以像下面一样使用资源: $smarty->display('extends:parent.tpl|child.tpl|grandchild.tpl'); 子{block}标签有*append*添加、*prepend*追加两个可选属性。在这样的情况下,父块内容可添加或追加子块内容。 {block name='title' append} My title {/block} php数据流: ======== (see online documentation) 参见在线手册 变量过滤器: ========= (see online documentation) 参见在线手册 访问静态类与命名空间支持 =================== 你可以在模板中通过namespace命名空间选项注册类,如下: $smarty->register->templateClass('foo','name\name2\myclass'); 在模板中像这样使用: | ~~~ {foo::method()} 等等 ~~~ | |-----| ======================= Please look through it and send any questions/suggestions/etc to the forums. 浏览下面这个网址,在论坛中发表任何问题、建议等 [http://www.phpinsider.com/smarty-forum/viewtopic.php?t=14168](http://www.phpinsider.com/smarty-forum/viewtopic.php?t=14168) Monte and Uwe <table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0"><tr><td width="33%" align="left" valign="top"><a href="smarty3.smarty2.bc.notes.html" accesskey="P">Prev</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">Home</a></td><td width="33%" align="right" valign="top"><a href="list.html">Next</a></td></tr><tr><td width="33%" align="left" valign="top">SMARTY2_BC_NOTES<br/> 2.x版本升级至3.x版本的提示</td><td width="34%" align="center" valign="top"><a href="appendixes.html" accesskey="U">Up</a></td><td width="33%" align="right" valign="top">LIST<br/> 翻译人员列表</td></tr></table>