跳至内容

模板资源

文件系统资源

到目前为止,在我们的示例中,我们加载模板时使用了简单的文件名或路径。

例如,要从文件系统加载名为 homepage.tpl 的模板文件,您可以编写

<?php

use Smarty\Smarty;
$smarty = new Smarty();

$smarty->display('homepage.tpl');

文件系统是默认资源。但是,模板可能来自各种来源。当您渲染模板或从另一个模板中包含模板时,您提供资源类型,后跟 以及适当的路径和模板名称。

如果未明确给出资源,则假定为默认资源类型。文件系统资源类型为 file,这意味着可以将前面的示例重写为

<?php

use Smarty\Smarty;
$smarty = new Smarty();

$smarty->display('file:homepage.tpl');

file 资源从使用 Smarty::setTemplateDir() 指定的目录中提取模板源文件(请参见配置 Smarty)。

setTemplateDir 接受一个单一路径,但也可以随着一个路径数组来调用。在这种情况下,目录列表以它们在数组中出现的顺序遍历。第一个找到的模板是处理的模板。

特定目录中的模板

Smarty 3.1 引入了一种采用方括号语法的方式来对元素进行指定,此语法起源于 Smarty::setTemplateDir()。这使得使用多个模板集的网站对要访问的模板拥有了更好的控制权限。

方括号语法可如下所示使用

<?php

// setup template directories
$smarty->setTemplateDir([
    './templates',            // element: 0, index: 0
    './templates_2',          // element: 1, index: 1
    '10' => 'templates_10',   // element: 2, index: '10'
    'foo' => 'templates_foo', // element: 3, index: 'foo'
]);

/*
  assume the template structure
  ./templates/foo.tpl
  ./templates_2/foo.tpl
  ./templates_2/bar.tpl
  ./templates_10/foo.tpl
  ./templates_10/bar.tpl
  ./templates_foo/foo.tpl
*/

// regular access
$smarty->display('file:foo.tpl'); 
// will load ./templates/foo.tpl

// using numeric index
$smarty->display('file:[1]foo.tpl'); 
// will load ./templates_2/foo.tpl

// using numeric string index
$smarty->display('file:[10]foo.tpl'); 
// will load ./templates_10/foo.tpl

// using string index
$smarty->display('file:[foo]foo.tpl'); 
// will load ./templates_foo/foo.tpl

// using "unknown" numeric index (using element number)
$smarty->display('file:[2]foo.tpl'); 
// will load ./templates_10/foo.tpl

而且,在 Smarty 模板的内部

{include file="file:foo.tpl"}
{* will load ./templates/foo.tpl *}

{include file="file:[1]foo.tpl"}
{* will load ./templates_2/foo.tpl *}

{include file="file:[foo]foo.tpl"}
{* will load ./templates_foo/foo.tpl *}

使用绝对路径

未包含在指定模板目录中的模板需要 file: 模板资源类型,后跟模板的绝对路径(带前导斜杠)。

<?php
$smarty->display('file:/export/templates/index.tpl');
$smarty->display('file:/path/to/my/templates/menu.tpl');
````

And from within a Smarty template:
```smarty
{include file='file:/usr/local/share/templates/navigation.tpl'}

说明

如果启用了 Security,则不允许访问不在指定模板目录之外的模板,除非你对这些目录设置白名单。

Windows 文件路径

如果你的运行系统是 Windows,文件路径通常会在路径名称的开头包含驱动器号(例如 C:)。一定要在路径中使用 file: 来避免命名空间冲突并获得所需的结果。

<?php
$smarty->display('file:C:/export/templates/index.tpl');
$smarty->display('file:F:/path/to/my/templates/menu.tpl');

而且在 Smarty 模板的内部

{include file='file:D:/usr/local/share/templates/navigation.tpl'}

处理缺少的模板

如果文件资源未找到请求的模板,它会检查是否有要调用的默认模板处理程序。默认情况下,没有默认模板处理程序,Smarty 会返回一个错误,但你可以注册一个默认模板处理程序,方法是使用任何 callable 调用 Smarty::registerDefaultTemplateHandler

<?php

$smarty->registerDefaultTemplateHandler([$this, 'handleMissingTemplate']);

// ...

public function handleMissingTemplate($type, $name, &$content, &$modified, Smarty $smarty) {
    if (/* ... */) {
        // return corrected filepath
        return "/tmp/some/foobar.tpl";
    } elseif (/* ... */) {
        // return a template directly
        $content = "the template source";
        $modified = time();
        return true;
    } else {
        // tell smarty that we failed
        return false;
    }
}

字符串和 eval 资源

Smarty 可以使用 string:eval: 资源通过一个字符串来渲染模板。

  • string: 资源的行为与模板文件非常类似。模板源自一个字符串被编译,并将编译后的模板代码存储起来备后用。每个唯一的模板字符串会创建一个新的已编译模板文件。如果频繁访问你的模板字符串,这是一个不错的选择。如果你有频繁改变的模板字符串(或利用率低的字符串),eval: 资源会是一个更好的选择,因为它不会将已编译的模板保存到磁盘。

  • 每次渲染某个页面时,eval: 资源都会评估模板源。这是利用率低的字符串不错的选择。如果频繁访问同一个字符串,string: 资源会是一个更好的选择。

说明

对于 string: 资源类型,每个唯一的字符串都会生成一个已编译文件。Smarty 无法检测到已经改变的字符串,因此会针对每个唯一的字符串生成一个新的已编译文件。选择正确的资源非常重要,这样才能避免用浪费的已编译字符串来填满你的磁盘空间。

<?php
$smarty->assign('foo', 'value');
$template_string = 'display {$foo} here';
$smarty->display('string:' . $template_string); // compiles for later reuse
$smarty->display('eval:' . $template_string); // compiles every time
在 Smarty 模板的内部
{include file="string:$template_string"} {* compiles for later reuse *}
{include file="eval:$template_string"} {* compiles every time *}

string:eval: 资源都可以通过 urlencode()base64_encode() 进行编码。对于通常使用 string:eval: 的情况,此操作不是必须的,但当使用其中一种情况时,配合 extends 资源时它又是必须的。

 <?php
 $smarty->assign('foo','value');
 $template_string_urlencode = urlencode('display {$foo} here');
 $template_string_base64 = base64_encode('display {$foo} here');
 $smarty->display('eval:urlencode:' . $template_string_urlencode); // will decode string using urldecode()
 $smarty->display('eval:base64:' . $template_string_base64); // will decode string using base64_decode()

在 Smarty 模板的内部

 {include file="string:urlencode:$template_string_urlencode"} {* will decode string using urldecode() *}
 {include file="eval:base64:$template_string_base64"} {* will decode string using base64_decode() *}

extends 资源

extends: 资源用于定义子/父关系。有关详细信息,请参见模板继承部分。

说明

通常不必使用 extends 资源。如果可以选择,那么使用 {extends} 标签从模板内部处理继承链通常更灵活且更直观。

使用 string:eval: 模板时,请确保它们是 url 或 base64 正确编码。

继承链中的模板不是单独编译的。只生成一个编译模板。(如果在继承链中找到了 eval: 资源,它的“不保存编译文件”属性将被 extends: 资源替换。)

示例

<?php
$smarty->display('extends:parent.tpl|child.tpl|grandchild.tpl'); 

// inheritance from multiple template sources
$smarty->display('extends:db:parent.tpl|file:child.tpl|grandchild.tpl|eval:{block name="fooBazVar_"}hello world{/block}'); 

stream 资源

Smarty 允许你将 PHP 流用作模板资源。Smarty 将首先查找已注册的模板资源。如果没有找到任何内容,它将检查是否提供了 PHP 流。如果流可用,Smarty 将使用它获取模板。

例如,

<?php
stream_wrapper_register('myresource', MyResourceStream::class);
$smarty->display('myresource:bar.tpl');

或者,从模板内部

 {include file="myresource:bar.tpl"}

添加您自己的资源类型

你可以创建一个扩展 Smarty\Resource\CustomPlugin 的类,以添加你自己的资源类型,例如从数据库加载模板。

例如

<?php
class HelloWorldResource extends Smarty\Resource\CustomPlugin {

    protected function fetch($name, &$source, &$mtime) {
        $source = '{$x="hello world"}{$x}'; // load your template here based on $name
        $mtime = time();
    }

}

// ..

$smarty->registerResource('helloworld', new HelloWorldResource());

如果某个 Resource 的模板不能通过 Smarty 编译器运行,该自定义 Resource 可能会扩展 \Smarty\Resource\UncompiledPlugin。然后,Resource Handler 必须实现函数 renderUncompiled(\Smarty\Template $_template)$_template 是对当前模板的引用,并且包含所有已分配的变量,实施者可以通过 $_template->getSmarty()->getTemplateVars() 访问这些变量。这些 Resource 只会将它们的渲染内容回显到输出流中。如果 Smarty 实例已作相应配置,则渲染后的输出将进行输出缓存。请参阅 src/Resource/PhpPlugin.php 以获取示例。

如果 Resource 编译后的模板不能缓存到磁盘,则自定义 Resource 可能会扩展 \Smarty\Resource\RecompiledPlugin。这些 Resource 在每次访问时都会进行编译。这可能会产生昂贵的开销。请参阅 src/Resource/StringEval.php 以获取示例。

更改默认资源类型

默认的资源类型是 file。如果要更改它,请使用 Smarty::setDefaultResourceType

以下示例将把默认资源类型更改为 mysql

<?php
$smarty->setDefaultResourceType('mysql');