phly/mustache

此包已被废弃,不再维护。作者建议使用phly/phly-mustache包。

PHP 5.3 Mustache实现

1.2.2 2015-09-01 20:08 UTC

This package is auto-updated.

Last update: 2022-02-01 12:20:02 UTC


README

已移动!

此包已移动到phly/phly-mustache,包名已更改为phly/phly-mustache

我已经更新了Packagist,将phly/mustache标记为废弃,并将用户指向新的包名。所有之前的版本都在旧包名下可用,功能相同。但是,新包包含v2代码,这以前从未以旧名称发布。

Phly\Mustache是为PHP 5.3+编写的Mustache(http://mustache.github.com)实现。它遵循mustache的原则,并允许通过语法定义扩展格式。

有关完整文档,请访问ReadTheDocs

邮件列表位于https://groups.google.com/d/forum/phly_mustache

目前,Phly\Mustache支持以下功能

  • PhlyTest\Mustache\Mustache

    • 渲染字符串模板
    • 渲染文件模板
    • 可以使用对象属性进行替换
    • 可以使用方法返回值进行替换
    • 模板可以使用条件
    • 如果值为假,则跳过条件
    • 如果值为空,则跳过条件
    • 模板迭代数组
    • 模板迭代可遍历对象
    • 高阶部分从内向外渲染
    • 模板将解除嵌套数组的引用
    • 模板将解除嵌套对象的引用
    • 倒置部分在空值上渲染
    • 渲染部分
    • 允许别名部分
    • 转义标准字符
    • 三重mustache阻止转义
    • 尊重隐式迭代语法定义
    • 允许设置替代模板后缀
    • 从渲染输出中删除注释
    • 允许指定替代分隔符
    • 仅在部分中设置替代分隔符仅适用于该部分
    • 替代分隔符适用于子部分
    • 替代分隔符不会传递给部分
    • 语法定义于部分特定
    • 语法定义不扩展到部分
    • 处理递归部分
    • 词法分析器从令牌中删除不需要的空白
    • 引用到php内置函数的数组值不应调用它们
    • 引用到php内置函数的对象属性不应调用它们
    • 引用到静态方法的数组值不应调用它们
    • 引用到函数的字符串值不应调用它们
    • 使用数组语法引用到静态方法的数组值不应调用它们
    • 作为视图的Std类不应引发错误
    • 点符号扩展到视图的子属性
    • 使用点符号,如果子属性不存在,则渲染空字符串
  • PhlyTest\Mustache\HierarchicalViews

    • 理解分层模板
    • 占位符作为未命名的部分渲染
    • 只有具有替换的占位符才接收替换
    • 可以渲染多个占位符
    • 可以渲染嵌套子占位符
    • 嵌套子可以渲染在父子中定义的占位符
  • PhlyTest\Mustache\DefaultResolver

    • 默认使用mustache后缀解析
    • 使用提供的后缀解析
    • 使用指定的目录分隔符解析
    • 内部使用路径栈
  • PhlyTest\Mustache\Pragma\SubViews

    • 子视图内容被捕获在父视图
    • 渲染嵌套子视图
    • 当没有提供视图时,子视图使用父视图
    • 应渲染闭包返回的子视图
    • 组成子视图的标准类不应引发错误

架构

Phly\Mustache由五个主要类组成

  • 词法分析器:将mustache语法进行分词。
  • 渲染器:使用视图提供的替换项渲染一系列标记。
  • Pragma:pragma的接口,可能修改如何处理标记
  • 解析器:将模板名称解析为mustache语法或标记。
  • Mustache:门面/网关类。分词和渲染模板,缓存标记,提供部分别名,并作为最终用户的主要接口。

用法

用法相当简单

include '/path/to/library/Phly/Mustache/_autoload.php';
use Phly\Mustache\Mustache;

$mustache = new Mustache();
echo $mustache->render('some-template', $view);

默认情况下,phly_mustache将在当前目录下查找以'.mustache'结尾的模板;您可以使用setTemplatePath()方法创建要搜索的目录堆栈

$mustache->setTemplatePath($path1)
         ->setTemplatePath($path2);

在上面的例子中,它将首先搜索$path2,然后是$path1以解析模板。

您还可以更改它将用于解析模板的后缀

$mustache->setSuffix('html'); // use '.html' as the suffix

如果您的模板使用pragma,您必须首先将pragma处理器添加到渲染器中。这可以通过以下方式完成

use Phly\Mustache\Pragma\ImplicitIterator as ImplicitIteratorPragma;
$mustache->getRenderer()->addPragma(new ImplicitIteratorPragma());
$mustache->render('template-with-pragma', $view);

视图可以是关联数组或对象。对于对象,任何公共成员(属性或方法)都可以在模板中引用。以下是一个示例

class View
{
    public $first_name = 'Matthew';

    public $last_name  = "Weier O'Phinney";

    public function full_name()
    {
        return $this->first_name . ' ' . $this->last_name;
    }
}

任何属性(或数组键)也可以引用有效的回调;在这种情况下,将使用回调的返回值。

$view = new \stdClass;
$view->first_name = 'Matthew';
$view->last_name  = "Weier O'Phinney";
$view->full_name  = function() use ($view) {
    return $view->first_name . ' ' . $view->last_name;
};

以下部分详细介绍了phly_mustache的独特和/或高级特性。

自动加载

phly_mustache遵循PSR-0标准,这意味着任何PSR-0兼容的类加载器都将工作。为了简化事情,组件包含一个"_autoload.php"文件,该文件将使用spl_autoload注册phly_mustache组件的自动加载器。您可以简单地包含该文件,然后开始使用phly_mustache。

高阶部分

"高阶部分"指的是返回回调的回调。以下是一个示例模板

{{#bolder}}Hi {{name}}.{{/bolder}}

以及以下视图

$view = new \stdClass;
$view->name = 'Tater';
$view->bolder = function() {
    return function($text, $renderer) {
        return '<b>' . $renderer($text) . '</b>';
    };
};

在这种情况下,部分的内容,“Hi {{name}}。”将作为第一个参数传递给部分,并将一个能够渲染的回调传递作为第二个参数(这基本上是一个在当前Renderer对象上curry并调用适当方法的闭包)。这允许您重用给定的“部分”来创建可重用的功能;将其视为类似Zend_View、Solar_View、Savant等系统中的“视图助手”。

部分

部分是Mustache中的一种基本包含形式;任何您发现可重用模板块的地方,都将其移动到部分中,并从父模板中引用该部分。

通常,您将在模板中使用标准语法引用部分

{{>partial-name}}

但是,您可以在渲染时可选地传递部分列表。当这样做时,列表应是一组别名/模板对

$mustache->render($template, array(), array(
    'winnings' => 'user-winnings',
));

在上面的示例中,'winnings'指的是模板"user-winnings.mustache"。因此,在正在渲染的$template中,您可以引用以下部分

{{>winnings}}

它将解析为适当的别名模板。

使用部分时要注意以下几点

  • 父模板可能更改标签分隔符,但如果您想在您的部分中使用相同的分隔符,则需要做出相同的声明。
  • 父模板可能使用一个或多个约定,但这些声明不会持久到部分;如果您想使用这些约定,必须在您的部分中引用它们。

基本上,部分在自己的作用域中渲染。如果您记住这个规则,就不应该有问题。

层次视图和占位符

(从版本1.1.0开始可用)。

占位符基本上是无名部分,由{{$name}}{{/name}}的组合表示。当渲染器遇到时,任何必须内容都将按正常必须内容渲染。

占位符主要用于层次视图的概念。这些由{{<name}}{{/name}}的组合表示。当遇到时,由name表示的模板将被标记化,并且在内容中定义的任何占位符都将用来替换父模板中找到的占位符。

例如,考虑以下父模板,“super.mustache”

<html>
<head><title>{{$title}}Default title{{/title}}</title></head>
<body>
<div class="content">
{{$content}}Default content of the page{{/content}}
</div>
</body>
</html>

如果单独渲染,将得到以下结果

<html>
<head><title>Default title</title></head>
<body>
<div class="content">
Default content of the page
</div>
</body>
</html>

现在,考虑以下子模板,“sub.mustache”

{{<super}}
{{$title}}Profile of {{username}}{{/title}}
{{$content}}
Here is {{username}}'s profile page
{{/content}}
{{/super}}

如果我们有一个将“username”定义为“Matthew”的视图并渲染“sub.mustache”,我们将会得到以下结果

<html>
<head><title>Profile of Matthew</title></head>
<body>
<div class="content">
Here is Matthew's profile page
</div>
</body>
</html>

注意子模板保留了父模板的视图上下文,并且它定义的所有mustache标记都像它们是另一个mustache模板一样渲染。

层次模板可以嵌套任意深度。

(这个功能受到了https://gist.github.com/1854699的启发)

空格删除

因为这是一个非常字面的编译器,空格有时可能成为问题。已经内置了一些措施来通过删除某些标记周围的空格(主要是换行符)来减少此类问题,但这会带来轻微的性能损失。

对于XML、XHTML或HTML5等标记语言,您可能不会在最终渲染输出中遇到问题。因此,您可以选择禁用空格删除

$mustache->getLexer()->disableStripWhitespace(true);

缓存标记

解析模板的标记可以缓存以供以后使用;或者,可以使用来自先前实例的缓存标记来初始化phly_mustache的新实例。

要获取标记列表,使用以下方法

$tokens = $mustache->getAllTokens();

这将返回一个模板名称/标记列表对的列表,基于此实例编译的模板。然后您可以使用以下方法用另一个实例来初始化

$mustache->restoreTokens($tokens);

这将覆盖该实例已编译的任何标记。

由于标记是模板名称/标记列表对,您可以安全地将它们传递给array_merge(),允许多个phly_mustache实例构建大量的模板标记缓存。这将极大地提高在后续调用中渲染模板时的性能--特别是如果您在内存存储(如memcached)中缓存标记。

约定

约定的形式是

{{%PRAGMA-NAME option=value}}

其中选项是键值对,完全是可选的。约定是用户定义的,可以用来扩展和/或修改渲染器的功能。

约定应实现Phly\Mustache\Pragma,它定义了检索约定名称(在约定注册期间使用,并由模板引用;当前情况下是区分大小写的),确定是否可以拦截特定标记类型的渲染,以及处理标记的方法。

约定应在渲染引用它们的任何模板之前注册。

$this->mustache->getRenderer()->addPragma($pragmaObject);
// ...
$this->mustache->render(/*...*/);

在模板中声明后,它们将在当前作用域内存在,这意味着

  • 如果在某个部分中声明,它们仅适用于该部分及其所有子部分
  • 如果为文件声明,它们仅适用于该文件及其所有子部分
  • 预处理器永远不会传递给部分;每个部分都使用一个空的预处理器集合进行渲染,并且必须声明它所需的任何预处理器以进行适当的渲染。

有关如何使用或实现预处理器的一些想法,请查看phly_mustache附带预处理器。

phly_mustache附带预处理器

IMPLICIT-ITERATOR 此预处理器允许迭代索引数组或具有标量值的可遍历对象,并可选择指定模板内使用的迭代器“键”。默认情况下,变量键“.”将被迭代器的当前值替换。

一个示例模板

{{#some_iterable_data}}
    {{.}}
{{/some_iterable_data}}

要使用显式迭代器键,通过预处理的“iterator”选项指定它

{{%IMPLICIT-ITERATOR iterator=bob}}
{{#some_iterable_data}}
    {{bob}}
{{/some_iterable_data}}

SUB-VIEWS Sub-Views预处理器允许您使用Mustache实现两步视图模式。当处于活动状态时,任何值是Phly\Mustache\Pragma\SubView实例的变量将被替换为渲染该对象封装的模板和视图。

SubView类使用模板名称和视图作为构造函数

use Phly\Mustache\Pragma\SubView;
$subView = new SubView('some-partial', array('name' => 'Matthew'));

然后,将该对象分配给视图键的值

$view = new \stdClass;
$view->content = $subView;

模板可能看起来像这样

{{!layout}}
{{%SUB-VIEWS}}
<html>
<body>
    {{content}}
</body>
</html>

部分可能看起来像这样

{{!some-partial}}
Hello, {{name}}!

渲染视图

use Phly\Mustache\Mustache,
    Phly\Mustache\Pragma\SubViews;
$mustache = new Mustache();
$subViews = new SubViews($mustache);
$rendered = $mustache->render('layout', $view);

将产生

<html>
<body>
    Hello, Matthew!
</body>
</html>

子视图可以嵌套和重复使用。