earc / native-php-template-engine
本机面向对象的PHP模板引擎。
Requires
- php: ^7.2 || ^8.0
Requires (Dev)
- phpunit/phpunit: ^7.5
This package is auto-updated.
Last update: 2024-09-29 05:29:08 UTC
README
轻量级、无依赖的模板组件,是earc框架的一部分,用于SOLID渲染方法。
利用面向对象编程的强大功能,使您的模板可重用且易于理解。
目录
安装
$ composer require earc/native-php-template-engine
引导
earc/native-php-template-engine不需要引导。
配置
earc/native-php-template-engine不需要配置。
基本使用
您可以渲染HTML、XML以及任何其他结构化或非结构化输出。
模板
模板是扩展AbstractTemplateModel的简单对象。您可以使用面向对象编程的全部功能,甚至依赖注入。
模板实现了template方法。在此方法内部输出的所有内容都是模板的渲染结果。您可以利用PHP将代码块外的代码视为纯输出的特性。
use eArc\NativePHPTemplateEngine\AbstractTemplateModel; class MyTemplate extends AbstractTemplateModel { /** @var object */ protected $object; /** @var int */ public $value; public function __construct(object $object, int $value) { $this->object = $object; $this->value = $value; } public function template() : void { ?> <h1>Hello World</h1> <p>I have found a value `<?= $this->value ?>`.</p> <p>May be the object with the id `<?= $this->object->getId() ?>` can tell me what to do with it.</p> <?php } }
提示:识别PHP的短输出语法(<?= .* ?>)。
最佳实践是只使用可以转换为字符串的属性。所有逻辑都必须外包到服务、实体、模型、转换器等中。即使是if和loop也不应出现在template方法内部,尽管它们可以通过底层的属性识别。
属性逻辑
即使从template方法中移除了所有逻辑,模板模型中仍需保留三个基本操作:if、include和loop。它们通过属性类型实现。
-
IF:通过
nullable属性实现。(null将转换为空字符串。) -
INCLUDE:可以通过模板内的模板实现复杂的树状结构。
use eArc\NativePHPTemplateEngine\AbstractTemplateModel; class MyRootTemplate extends AbstractTemplateModel { /** @var AbstractTemplateModel */ protected $head; /** @var AbstractTemplateModel */ protected $body; public function __construct(AbstractTemplateModel $head, AbstractTemplateModel $body) { $this->head = $head; $this->body = $body; } public function template() : void { ?><!DOCTYPE html> <html lang="en"> <head> <title>I am fixed content.</title> <?= $this->head ?> </head> <body> <?= $this->body ?> </body> <?php } }
-
LOOP:要将
loop渲染为iterable,请将iterable注入到新的IteratorTemplateModel实例中。use eArc\NativePHPTemplateEngine\AbstractTemplateModel; use eArc\NativePHPTemplateEngine\IteratorTemplateModel; class MyTemplate extends AbstractTemplateModel { /** @var IteratorTemplateModel */ protected $loop; public function __construct(iterable $iterable) { $this->loop = new IteratorTemplateModel($iterable); } public function template() : void { ?> <div> The iterables items are cast to string on rendering: <?= $this->loop ?> </div> <?php } }
属性逻辑可以帮助您在模板中遵循单一职责原则。保持代码整洁,并使模板易于理解。
渲染
要渲染模板,只需将模板模型/对象转换为字符串。
$template = new MyTemplate($object, $value); $renderedTemplate = (string) $template;
您可以直接输出类。PHP会隐式地进行转换。
echo new MyTemplate($object, $value);
渲染JSON对象
有时您不需要HTML,而是需要数据。json_encode将公共属性转换。这可以用于在一个输出数据模型中结合两个目的。
echo json_encode(new MyTemplate($object, $value);
如果您愿意,当然可以同时发送它们。
$template = new MyTemplate($object, $value); echo json_encode(['data' => $template, 'html' => (string) $template]);
助手
为了使基本使用工作,earc/native-php-template-engine仅使用41行代码。
有时您可能需要一些额外的帮助来加速编码。earc/native-php-template-engine附带了许多助手。
模板模型接口
编写模板是关于增强数据输出。复杂的数据类型通常是对象,如果它们是可持久化的,则称为实体。如果它们可以直接转换为字符串,那岂不是很好?
使用__toString()方法有一些缺点
- 它可能已被用于其他目的。
- 一个对象可能存在多个模板。
- 构建模板可能需要一些额外的信息。
使用 TemplateModelInterface 提供了一种更加灵活的方式。类型转换足够简单
(string) $entity->getTemplate();
原则上,这是一个两步的类型转换。首先将实体对象转换成相关模板对象。然后,将模板对象转换成字符串。
如果有多个模板,提供模板的完全限定类名
(string) $entity->getTemplate(MyEntityTemplate::class);
如果模板需要构建一些额外的信息,则不应通过对象的模板工厂来构建。这样的工厂会超出转换的目的,因此违反了单一职责原则。使用传统方式
(string) new MyEntityTemplate($entity, $additionalParameter);
当然,您需要实现 TemplateModelInterface。
use eArc\NativePHPTemplateEngine\helpers\TemplateModelInterface; class SomeEntity implements TemplateModelInterface { // ... public function getTemplate(?string $fQCN = null) { if (null === $fQCN) { return new SomeEntityDefaultTemplate($this); } return new $fQCN($this); } }
集合模板模型
只要项目的类型转换能够得到期望的结果,IteratorTemplateModel 就可以正常工作。预处理是可能的,但这是一项足够愚蠢的任务
use eArc\NativePHPTemplateEngine\AbstractTemplateModel; use eArc\NativePHPTemplateEngine\IteratorTemplateModel; class MyTableTemplate extends AbstractTemplateModel { // ... public function __construct($collection) { $tmplCollection = []; foreach ($collection as $entity) { $tmplCollection[] = new EntityDefaultTemplate($entity); } $this->collection = new IteratorTemplateModel($tmplCollection); } // ... }
CollectionTemplateModel 会为您完成那些无聊的部分。
use eArc\NativePHPTemplateEngine\helpers\CollectionTemplateModel; // ... $this->collection = new CollectionTemplateModel($collection, EntityDefaultTemplate::class);
如果您的集合实现了 TemplateModelInterface,则可以省略完全限定类名。
use eArc\NativePHPTemplateEngine\helpers\CollectionTemplateModel; // ... $this->collection = new CollectionTemplateModel($collection);
甚至可以将参数传递给模板的构造函数。
use eArc\NativePHPTemplateEngine\helpers\CollectionTemplateModel; // ... // calls internally: new EntityDefaultTemplate($collectionItem, $some, $arguments) $this->collection = new CollectionTemplateModel($collection, EntityDefaultTemplate::class, $some, $arguments); //...
HTML
属性
选择
发布
版本 1.0
- 仅支持 PHP ^8.0
- 简化了 API
- 渲染属性的访问级别为 public
IteratorTemplateModel的构造函数接受iterable<string|TemplateInterface>- 通用 HTML 元素模板
版本 0.3
- 支持 PHP ^8.0
版本 0.2
- 为
OptionTemplateModel和OptGroupTemplateModel添加了callable类型参数
版本 0.1
- 添加了
TemplateInterface和TemplateTrait
版本 0.0
- 首次发布