lucinda / view-language
针对PHP应用的高性能视图模板API,受Java JSTL和C编译器启发,使用标签和表达式
Requires
- php: ^8.1
- ext-simplexml: *
Requires (Dev)
- lucinda/unit-testing: ^2.0
- dev-master
- v4.0.x-dev
- v4.0.4
- v4.0.3
- v4.0.2
- v4.0.1
- v4.0.0
- v3.1.0
- v3.0.x-dev
- v3.0.10
- v3.0.9
- v3.0.8
- v3.0.7
- v3.0.6
- v3.0.5
- v3.0.4.1
- v3.0.4
- v3.0.3.1
- v3.0.3
- v3.0.2
- v3.0.1.1
- v3.0.1
- v3.0.0
- v2.1.12
- v2.1.11
- v2.1.10
- v2.1.9
- v2.1.8
- v2.1.7
- v2.1.6.3
- v2.1.6.2
- v2.1.6.1
- v2.1.6
- v2.1.5
- v2.1.4.2
- v2.1.4.1
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.x-dev
- v2.0.2
- v2.0.1
- v2.0.0
- v1.3.1
- v1.3.0.1
- v1.3.0
- v1.2.3.3
- v1.2.3.2
- v1.2.3.1
- v1.2.3
- v1.2.2.1
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.x-dev
- v1.0.0
This package is auto-updated.
Last update: 2024-09-04 14:29:57 UTC
README
目录
关于
此API是ViewLanguage模板引擎的PHP编译器,一种受Java JSP&JSTL启发的标记语言,作为HTML标准的扩展,旨在通过通过以下方式完全消除视图中的脚本需求:
为了实现其目标,需要遵循以下步骤
- 配置:设置一个XML文件,其中配置模板
- 编译:使用Lucinda\Templating\Wrapper读取上述XML并编译模板
API完全遵循PSR-4规范,仅需要PHP8.1+解释器和SimpleXML扩展。要快速了解其工作原理,请查看
- 安装:描述如何在您的计算机上安装API,考虑到上述步骤
- 单元测试:API具有100%的单元测试覆盖率,使用UnitTest API而不是PHPUnit,以获得更大的灵活性
- 示例:展示了如何使用ViewLanguage进行模板化,包括每个步骤的解释
- 参考指南:显示了API附带的所有标签列表
表达式
一个表达式是ViewLanguage中表示脚本变量的表示。表达式的语法是
${variableName}
其中variableName可以是
一个非常强大的功能是嵌套表达式的能力:编写其键本身是表达式的表达式。这可以任何深度进行,当迭代多个列表并将一个与另一个的键/值关联链接时非常有用
标签
一个标签是ViewLanguage中表示脚本逻辑的表示。所有标签都像HTML标准的扩展一样工作,因此它们有名称、可选属性和主体。ViewLanguage已知有两种类型的标签
一个非常强大的功能是标签的递归能力:允许在视图语言标签内嵌套视图语言标签。每当发生这种情况时,编译器会逐步深入,直到没有标签为止!
宏标签
宏标签的工作方式类似于C宏:在代码编译之前,它们会被读取并“展开”,以便编译可以在整个源代码上运行。语法与普通HTML标签相同。
<NAME ATTRIBUTE="value" .../>
位置
- NAME:执行单个逻辑操作的标签名称。
- ATTRIBUTE:配置标签行为。
API定义以下宏标签
- escape:编译器会忽略其主体的标签。这在标记内容时不希望被解析时是必要的。
- import:编译器会用其“file”属性指向的文件的主体替换其声明。这对于布局/模板化至关重要。
- namespace:编译器会告知其在哪里查找默认文件夹中找不到的标签库。
目前,用户无法定义自己的宏标签!
库标签
库标签是可以编译的API/用户定义的HTML片段,预期在视图语言应用中实现脚本逻辑。它们是依赖于变量且无法通过 . 加载的非静态重复模板(HTML)代码片段。
它们的语法扩展了HTML标准
<LIBRARY:TAG ATTRIBUTE="value" ...>...</LIBRARY:TAG>
如果没有主体
<LIBRARY:TAG ATTRIBUTE="value" .../>
位置
- LIBRARY:包含在模板上执行相关逻辑操作的命名空间。规则
- 值必须为小写字母和数字。
- "-"符号也可以用于替换多词值中的空格
- TAG:执行单个逻辑操作的标签名称。规则
- 值必须为小写字母和数字。
- 符号也可以用于替换多词值中的空格
- ATTRIBUTE:配置标签行为(可以是零个或多个)。规则
- 名称必须为小写字母和数字。
- "_"符号也可以用于替换多词名称中的空格
- 值只能是原始数据(字符串或数字)或视图语言表达式。
- 与标准HTML不同,目前属性不能多行。
标准标签
API包括一个包含标签的标准库,其中LIBRARY为空时,用于编程语言指令。
- :for:遍历列表中的数字。
- :foreach:通过键和值遍历字典。
- :if:评估符合条件的主体。
- :elseif:评估不符合先前if/elseif条件的条件主体。
- :else:评估不符合先前if/else if的条件主体。
- :set:创建变量并/或为其设置值。
- :unset:取消变量。
- :while:在条件上执行循环。
- :break:结束循环。
- :continue:跳过当前循环的其余评估并移动到下一个迭代。
标准标签与以下类型的ATTRIBUTE值一起工作
- 标量:字符串或整数
- 表达式:ViewLanguage 表达式。如果将辅助函数用作属性值,则必须将其保持未装饰:count(${asd}) 而不是 ${count(${asd})}。
- 条件:预期语法类似于 C 语言,但最终匹配编译成语言代码的语法(在我们的例子中是 PHP)。例如:${x}==true 在 PHP 中表示 $x==true。
用户自定义标签
为了将 HTML 响应分解成离散的单位,开发者必须创建自己的库和标签。用户自定义标签根据以下规则在磁盘上找到
- 库的名称必须是编译时提供的 tags 文件夹内的一个文件夹
- 标签代码必须是库文件夹内与 name 名称相同的 HTML 文件
配置
为了配置此 API,您必须在 XML 中包含一个 templating 标签
<templating compilations_path="..." tags_path="..." templates_path="..." templates_extension="..." />
位置
- compilations_path:(必填)保存 ViewLanguage 模板 PHP 编译的路径
- tags_path:(可选)ViewLanguage 标签库的位置路径
- templates_path:(可选)模板的位置路径
- templates_extension:(可选)模板文件的扩展名。如果没有设置,则假设为 "html"!
示例
<templating compilations_path="compilations" tags_path="application/taglib" templates_path="application/views" templates_extension="html"/>
编译
完成上述步骤后,您需要实例化 Lucinda\Templating\Wrapper,以便以后能够编译模板
$wrapper = new Lucinda\SQL\Wrapper(simplexml_load_file(XML_FILE_NAME));
对象有以下方法,可用于编译一个或多个模板
模板是如何编译的?
与任何其他模板语言一样,编译首先遍历依赖关系的树形结构,并进一步组装结果到 PHP 文件中,然后通过绑定用户接收到的数据生成 HTML。因此,它涉及以下步骤
- 如果存在 $template 参数的 PHP 编译,则检查自上次更新以来内部引用的元素是否已更改。如果它不存在或已更改
- 在输出缓冲区中,加载编译文件,将其绑定到用户提供的 $data,并从中生成最终的 HTML
由于整个过程对性能有一定的需求,PHP 编译文件将缓存在磁盘上,并在下一次请求中直接返回,除非其组件(模板或标签)之一已更改。这使得 API 能够以约 0.001 秒的平均时间编译,从而不会带来任何性能开销,但提供了优雅视图的所有优点!
安装
首先选择 API 将要安装的文件夹,然后在控制台中使用以下命令
composer require lucinda/templating
然后创建一个包含配置设置的 configuration.xml 文件(请参阅上面的 配置),并在项目根目录中创建一个 index.php 文件,其中包含以下代码
require(__DIR__."/vendor/autoload.php"); $wrapper = new Lucinda\SQL\Wrapper(simplexml_load_file("configuration.xml"));
要编译模板
$html = $wrapper->compile(TEMPLATE_NAME, USER_DATA);
位置
- TEMPLATE_NAME 是必须遵守以下规则的 基础模板
- USER_DATA 是从后端获取并在模板中访问的值列表,遵守以下规则
- 必须是一个数组
- 条目键必须是字符串或整数(通常是 PHP 的要求)
- 条目值必须是标量或数组
- 如果数组是多维的,同级中的键和值必须遵守上述相同的规则
为了显示结果
header("Content-Type: text/html; charset=UTF-8"); echo $html;
单元测试
对于测试和示例,请检查 API 源中的以下文件/文件夹
- unit-tests.sql:在执行单元测试之前需要在服务器上运行一次的 SQL 命令(假设是 MySQL)
- test.php:在控制台中运行单元测试
- unit-tests.xml:设置单元测试并模拟 "sql" 标签
- tests:来自 src 文件夹的类的单元测试
示例
假设 configuration.xml (见 配置 和 安装) 是
<xml> <templating compilations_path="compilations" tags_path="application/taglib" templates_path="application/views" templates_extension="html"/> </xml>
让我们创建一个具有以下主体的 application/views/index.html 模板
<import file="header"/> Hello, dear ${data.author}! Author of: <ul> <:foreach var="${data.apis}" key="name" val="url"> <my:api id="${name}" link="${url}"/> </:foreach> </ul> <import file="footer"/>
上面的操作做了以下事情
- 加载 application/views/header.html 模板的主体
- 通过 表达式 输出 $data 中 author 数组的值
- 通过 <:foreach> 遍历 $data 中 apis 数组的值
- 在每次迭代中,加载 application/taglib/my/api.html 模板的主体(用户标签),将属性绑定到值
- 加载 application/views/footer.html 模板的主体
application/views/header.html 文件的内容
<html> <head> <title>View Language API Tutorial</title> </head> <body>
application/taglib/my/api.html 文件的内容
<li><a href="$[id]">$[link]</a></li>
application/views/footer.html 的内容
</body> </html/>
如上所示,模板依赖于从后端接收的变量(author & apis),这两个键都是 $data 数组的键。假设后者的值是
$data = [ "author" => "Lucian Popescu", "apis" => ["View Language API" => "https://www.lucinda-framework.com/view-language", "STDOUT MVC API" => "https://www.lucinda-framework.com/stdout-mvc"] ];
现在让我们编译 application/views/index.html 模板(见 编译)并将其绑定到 $data
require(__DIR__."/vendor/autoload.php"); $wrapper = new Lucinda\SQL\Wrapper(simplexml_load_file("configuration.xml")); $html = $wrapper->compile("index", $data);
首先,ViewLanguage 基础模板被编译成 PHP,结果保存到 compilations/index.php 文件中(如果尚未存在),以下是其主体
<html> <head> <title>View Language API Tutorial</title> </head> <body> Hello, <?php echo $data["author"]; ?>, author of: <ul> <?php foreach($data["apis"] as $name=>$url) { ?> <li><a href="<?php echo $url; ?>"><?php echo $name; ?></a></li> <?php } ?> </ul> </body> </html/>
然后,在输出缓冲区中加载上述文件,并与其绑定,因此最终返回的 HTML 将是
<html> <head> <title>View Language API Tutorial</title> </head> <body> Hello, Lucian Popescu, author of: <ul> <li><a href="https://www.lucinda-framework.com/view-language">View Language API</a></li> <li><a href="https://www.lucinda-framework.com/stdout-mvc">STDOUT MVC API</a></li> </ul> </body> </html/>
参考指南
标签转义
标记标签体以被 ViewLanguage 编译器忽略。语法
<escape> ... </escape>
如何将此标签编译成 PHP 的示例
标签导入
将另一个视图语言模板包含到当前模板中。语法
<import file="..."/>
属性
如何将此标签编译成 PHP 的示例
标签命名空间
标记用户定义标签库的定制位置(必须在后续声明之前放置)。语法
<namespace taglib="..." folder="..."/>
属性
如何将此标签编译成 PHP 的示例
标签 :for
创建一个 FOR 循环。语法
<:for var="..." start="..." end="..." (step="...")> ... </:for>
属性
如何将此标签编译成 PHP 的示例
标签 :foreach
创建一个 FOR EACH 循环。语法
<:foreach var="..." (key="...") val="..."> ... </:foreach>
属性
如何将此标签编译成 PHP 的示例
标签 :if
创建一个 IF 条件。语法
<:if test="..."> ... </:if>
如果后面跟着 :else 或 :elseif,则标签不得关闭!
属性
如何将此标签编译成 PHP 的示例
您也可以使用三元运算符从表达式中运行简单的 IF/ELSE 语句!
标签 :elseif
创建一个 ELSE IF 条件。语法
<:elseif test="..."> ... </:if>
如果后面跟着 :else 或 :elseif,则标签不得关闭!
属性
如何将此标签编译成 PHP 的示例
标签 :else
创建一个ELSE条件。语法
<:else> ... </:if>
如何将此标签编译成 PHP 的示例
标签 :set
将值赋给变量。语法
<:set var="..." val="..."/>
属性
如何将此标签编译成 PHP 的示例
标签 :unset
从内存中删除变量。语法
<:unset var="..."/>
属性
如何将此标签编译成 PHP 的示例
标签 :while
创建WHILE循环。语法
<:while test="..."> ... </:while>
属性
如何将此标签编译成 PHP 的示例
标签 :break
中断FOR/FOR EACH/WHILE语句循环。语法
<:break/>
如何将此标签编译成 PHP 的示例
标签 :continue
在FOR/FOR EACH/WHILE语句循环中继续到下一个步骤。语法
<:continue/>
如何将此标签编译成 PHP 的示例