icybee/patron

一个HTML模板引擎

v1.4.1 2016-07-08 22:23 UTC

This package is auto-updated.

Last update: 2024-09-20 07:26:24 UTC


README

Release Build Status HHVM Code Quality Code Coverage Packagist

Patron 是一个适用于 PHP5.4+ 的模板引擎。它促进了应用程序逻辑和内容与其展示的分离。模板是用 HTML 编写的,包括在模板解析时被替换的表达式,以及控制模板逻辑的特殊标记。

典型示例

<p:articles limit="10">
	<p:foreach>
		<article class="#{@css_class}">
			<h1>#{@title}</h1>

			<div class="article-body">#{@=}</div>

			<p:if test="@comments">
				<section class="article-comments">
					<h2>Comments</h2>

					<p:foreach in="@comments">
						<article class="#{@css_class}">
							<header>
							<h3>Comment №#{self.position} by #{@author}</h3>
							</header>

							<div class="comment-body">#{@=}</div>
						</article>
					</p:foreach>
				</section>
			</p:if>
		</article>
	</p:foreach>

	<p:pager />
</p:articles>

特性

  • 标记集和函数集易于扩展。
  • 块有一个 主题,类似于 JavaScript 中的 this
  • 使用 #{t:String to translate} 符号轻松翻译。

致谢

这个模板引擎的开发是在大约 2007 年,因为那时 textpattern 不支持嵌套标记,我觉得这会是一个很好的练习。其代码的一部分已经沉睡很长时间了,所以如果你看到一些驼峰式命名,尽管几乎到处都使用蛇形命名,但至少你能识别出 旧的 部分 :-)

表达式

使用 #{<expression>} 符号的表达式用于输出数据。除非在关闭 } 之前使用 = 修饰符,否则数据总是被转义。

#{@title}
#{@title.shuffle()}   <!-- `title` is passed to str_shuffle() -->
#{@title=}            <!-- `title` is not escaped -->

#{pagination=}        <!-- another variable that is not escaped -->

标记集合

可以由 Patron 引擎实例使用的标记定义在 MarkupCollection 实例中,该实例用于创建 Engine 实例。可以使用 get_markups() 辅助函数获取共享的标记集合。当它首次创建时,会触发 MarkupCollection\AlterEvent 类的 MarkupCollection::alter 事件。事件钩子可以使用此事件来修改集合,添加和删除标记定义。

以下示例演示了如何使用事件钩子添加一个支持默认为 "world" 的 name 参数的 hello 标记。

<?php

use Patron\Engine;
use Patron\MarkupCollection;

$app->events->attach(function(MarkupCollection\AlterEvent $event, MarkupCollection $collection) {

	$collection['hello'] = [ function(array $args, Engine $engine, $template) {

		return "Hello {$args['name']}!";

	}, [ 'name' => "world" ] ];

});

以下标记已定义。

p:if 标记

提供简单的 if-then 条件性。

<p:if
	test = expression
	select = expression
	equals = value>
	<!-- Content: p:with-param*, template -->
</p:if>

应定义 testselect 和一个运算符(例如 equals)。测试是静默的,不应生成通知。

<p:if test="@has_title">This article has a title</p:if>
<p:if test="@has_title.not()">This article has no title</p:if>
<p:if select="@comments_count" equals="10">This article has 10 comments</p:if>

p:choose 标记

从多个可能的替代方案中选择一个。

<!-- Category: instruction -->
<p:choose>
	<!-- Content: (p:when+, p:otherwise?) -->
</p:choose>

<p:when
	test = boolean-expression>
	<!-- Content: template -->
</p:when>

<p:otherwise>
	<!-- Content: template -->
</p:otherwise>

它由一系列 p:when 元素和一个可选的 p:otherwise 元素组成。每个 p:when 元素都有一个属性,test,指定一个表达式。p:whenp:otherwise 元素的内容是模板。当处理 p:choose 元素时,会按顺序测试每个 p:when 元素,通过评估表达式并将结果对象转换为布尔值(就像调用布尔函数一样)。第一个测试为真的 p:when 元素的内容被实例化。如果没有 p:when 为真,则实例化 p:otherwise 元素的内容。如果没有 p:when 元素为真,并且没有 p:otherwise 元素,则不创建任何内容。

p:foreach 标记

将模板应用于提供的数组中的每个条目。

<p:foreach
	in = expression | this
	as = qname | this>
	<!-- Content: p:with-param*, p:empty?, p:wrap?, template -->
</p:foreach>

在每次迭代中,以下变量将在 self 中更新

  • count:条目数。
  • position:当前条目的位置。
  • left:剩余条目数。
  • even:如果位置是偶数,则为 "even",否则为空字符串。
  • key:条目的键。
<p:foreach in="articles">
	<p:empty>There is no article yet.</p:empty>
	<p:wrap><ul>#{@=}</ul></p:wrap>
	
	<li>#{self.position}/#{self.count} <a href="#{@url}">#{@title}</a></li>
</p:foreach>

p:variable 标记

将名称绑定到值。

<!-- Category: top-level-element -->
<!-- Category: instruction -->
<p:variable
	name = qname
	select = expression>
	<!-- Content: p:with-param*, template? -->
</p:variable>

<!-- Category: top-level-element -->
<p:param
	name = qname
	select = expression>
	<!-- Content: template? -->
</p:param>

变量绑定的值(变量的值)可以是表达式可以返回的任何类型的对象。可以使用两个元素来绑定变量:p:variablep:with-param。区别在于,在 p:with-param 变量中指定的值仅为绑定的默认值;当调用包含 p:with-param 元素的模板时,可以传递参数,这些参数将用作默认值。

p:variablep:with-param 都有一个必需的 name 属性,该属性指定变量的名称。该 name 属性的值是一个限定名。

<p:variable name="count" select="@comments_count" />
<p:variable name="count">There are #{@comments_count} comments</p:variable>

p:with 标记

解析具有约束值的模板。

<p:with
	select = expression>
	<!-- Content: p:with-param*, template -->
</p:with>
<p:with select="articles.first().comments.last()">
Last comment: <a href="#{@url}">#{@title}</a>
</p:with>

p:decorate 标记

使用模板装饰内容。

<p:decorate
	with = string>
	<!-- Content: p:with-param*, template -->
</p:decorate>

将标记内容渲染以创建要装饰的组件,然后将其作为 component 变量传递给装饰模板。

使用 with 属性指定装饰模板的名称,例如,如果指定 "page",则使用模板 "@page.html" 或 "partials/@page.html",优先使用前者。

使用 with-param 指定的参数,以及标记的属性(除 with 外)在装饰模板中作为变量提供。

<p:decorate with="page">
	 <p:page:content id="body" />
</p:decorate>

@page.html 模板

<!DOCTYPE html>
<head>
</head>
<body>
	#{component=}
</body>

p:template 标记

添加模板。

<p:template
	name = qname>
	<!-- Content: p:with-param*, template -->
</p:template>

name 属性定义了模板的名称。标记的内容定义了模板。

p:call-template 标记

调用模板。

<p:call-template
	name = qname>
	<!-- Content: p:with-param* -->
</p:call-template>

p:translate 标记

翻译并插值字符串。

<p:translate
	native = string>
	<!-- Content: p:with-param* -->
</p:translate>

使用标记的属性或 with-param 构造提供插值的参数。

示例

<p:translate native="Posted on :date by !name">
	<p:with-param name="date"><time datetime="#{@date}" pubdate="pubdate">#{@date.format_date()}</time></p:with-param>
	<p:with-param name="name" select="@user.name" />
</p:translate>

p:document:css 标记

可以使用 p:document:css 元素收集 CSS 资产并将其渲染到 LINK 元素中。使用 href 属性将资产添加到集合中。使用 weight 属性指定该资产的权重。如果没有指定 weight 属性,则资产的权重默认为 100。如果没有指定 href 属性,则渲染资产。如果指定了模板,则将集合作为 this 传递,否则将集合渲染为 LINK 元素的 HTML 字符串。

注意:此标记需要 brickrouge/brickrouge 包。

<p:document:css
	href = string
	weight = int>
	<!-- Content: p:with-params, template? -->
</p:document:css>

示例

<p:document:css href="/public/page.css" />
<p:document:css href="/public/reset.css" weight="-100" />
<p:document:css />

将生成

<link href="/public/reset.css" type="text/css" rel="stylesheet" />
<link href="/public/page.css" type="text/css" rel="stylesheet" />

p:document:js 标记

可以使用 p:document:js 元素收集 JavaScript 资产并将其渲染到 SCRIPT 元素中。使用 href 属性将资产添加到集合中。使用 weight 属性指定该资产的权重。如果没有指定 weight 属性,则资产的权重默认为 100。如果没有指定 href 属性,则渲染资产。如果指定了模板,则将集合作为 this 传递,否则将集合渲染为 SCRIPT 元素的 HTML 字符串。

注意:此标记需要 brickrouge/brickrouge 包。

<p:document:js
	href = string
	weight = int>
	<!-- Content: p:with-params, template? -->
</p:document:js>

示例

<p:document:js href="/public/page.js" />
<p:document:js href="/public/reset.js" weight="-100" />
<p:document:js />

将生成

<script src="/public/reset.css" type="text/javascript"></script>
<script src="/public/page.css" type="text/javascript"></script>

p:pager 标记

渲染页面元素。

注意:此标记需要 brickrouge/brickrouge 包。

<p:pager
	count = int
	page = int
	limit = int
	with = string
	range = expression
	noarrows = boolean>
	<!-- Content: p:with-param*, template? -->
</p:pager>

函数集合

可以由Patron引擎实例使用的函数定义在FunctionCollection实例中,该实例用于创建Engine实例。可以使用get_functions()辅助函数来获取共享的标记集合。当它首次创建时,将触发类FunctionCollection\AlterEventFunctionCollection::alter事件。事件钩子可以使用此事件来修改集合,添加和删除函数。

以下示例演示了如何使用事件钩子添加一个hello函数

<?php

use Patron\Engine;
use Patron\FunctionCollection;

$app->events->attach(function(FunctionCollection\AlterEvent $event, FunctionCollection $collection) {

	$collection['hello'] = function($name="world") {

		return "Hello $name!";

	};

});

以下函数是默认定义的

  • if:如果a是真值,则返回b,否则返回c
  • or:如果a是真值,则返回a,否则返回b
  • not:返回否定值。
  • mod:两个值的模。
  • bit:检查是否定义了位。
  • greater:检查a是否大于b
  • smaller:检查a是否小于b
  • equals:检查a是否等于b
  • different:检查a是否不同于b
  • add:将两个值相加。
  • minus:从一个值中减去另一个值。
  • plus:将两个值相加。
  • times:乘以一个值。
  • by:除以一个值。
  • split:将字符串分割为数组。
  • joint:将数组连接成字符串。
  • index:返回指定索引的值。
  • first:返回数组的第一个元素,或前n个元素。
  • to_s:将值转换为字符串。
  • replace:替换字符串。
  • markdown:使用Markdown将字符串转换为HTML。

查找函数

使用find()方法在集合中查找函数,它还可以检查集合外部定义的函数,例如PHP函数。

<?php

echo $functions->find('boot'); // ICanBoogie\boot

执行函数

您可以使用find()方法查找函数,然后使用返回的值调用该函数,或者您可以直接像调用FunctionCollection的方法一样调用该函数。

<?php

use Patron\FunctionCollection;

$functions = new FunctionCollection([

	'hello' => function($name = "world") {
	 
	    return "Hello $name!";
	 
	 }

]);

echo $functions->hello("Olivier"); // Hello Olivier!

如果调用的函数未定义,将抛出FunctionNotDefined异常。

事件钩子

  • ICanBoogie\Core::boot:此事件用于将事件钩子附加到MarkupCollection::alterFunctionCollection::alter,以便添加在patron.markupspatron.function配置中定义的标记和函数。

要求

该包需要PHP 5.4或更高版本。

安装

推荐通过Composer安装此包。

$ composer require icybee/patron

以下包是必需的,您可能需要检查它们

克隆仓库

该包可在GitHub上找到,可以使用以下命令行克隆其仓库

$ git clone https://github.com/Icybee/Patron.git

文档

该包作为[ICanBoogie][]框架的一部分进行了文档说明文档。您可以使用make doc命令生成包及其依赖项的文档。文档生成在build/docs目录中。需要ApiGen。可以使用make clean命令清理该目录。

测试

测试套件使用make test命令运行。PHPUnitComposer需要全局可用才能运行套件。该命令按需安装依赖。执行make test-coverage命令将运行测试套件并在"build/coverage"目录中创建HTML覆盖率报告。该目录可以用make clean命令清理。

该软件包由Travis CI持续测试。

Build Status Code Coverage

许可证

本软件包受新BSD许可证的许可 - 详细信息请参阅LICENSE文件。