younishd/endobox

此包已被 废弃 且不再维护。未建议替代包。

最小的模板引擎。

v4.3.0 2020-06-24 12:36 UTC

This package is auto-updated.

Last update: 2023-11-06 04:29:13 UTC


README

endobox

endobox

最小的模板引擎。

Build Status Code Climate Latest Stable Version Total Downloads License

endobox

🌱 原生 PHP 语法 📝 内置 Markdown  🚀 最小化 API
使用纯 PHP 编写模板。无需学习新语法。 内置一个完整的 Markdown 解析器。是的,它可以与 PHP 结合使用! 只需几个基本方法即可完成强大的功能。

文档

安装

通过 Composer 安装 endobox

composer require younishd/endobox

您需要 PHP 7.0+

开始使用

配置 endobox 以加载应用程序模板的典型方式如下

require_once '/path/to/vendor/autoload.php';

use endobox\Endobox;

$endobox = Endobox::create('path/to/templates');

您可以添加额外的模板位置

$endobox->addFolder('another/path/to/templates');

渲染模板

为您的模板实例化一个 Box

$welcome = $endobox('welcome');

通过调用 render() 使用一些变量来渲染模板

echo $welcome->render([ 'name' => "Alice" ]);

模板文件可能看起来像这样

welcome.php
<h1>Hello, <?= $name ?>!</h1>

文件扩展名

endobox 根据文件扩展名来决定如何渲染模板。

但是,在实例化模板 Box 时,会省略扩展名。

$members = $endobox('members'); // no file extension

PHP: .php

PHP 模板通过评估 PHP 标签(即 <? … ?>)之间的代码并返回结果进行处理。

members.php
<h1>Members</h1>
<ul>
    <?php foreach ($users as $u): ?>
        <li><?= $u->name ?></li>
    <?php endforeach ?>
</ul>

ℹ️ 技巧: <?=<?php echo 的语法糖。

Markdown: .md

Markdown 模板通过 Markdown 解析器(Parsedown)进行处理,生成相应的 HTML 代码。这可以用于静态内容。

members.md
# Members

- Alice
- Bob
- Carol

PHP+Markdown: .md.php

正如其名所示,这种模板类型结合了 PHP 和 Markdown:模板首先被评估为 PHP,然后被解析为 Markdown。非常方便。

members.md.php
# Members

<?php foreach ($users as $u): ?>
    - <?= $u->name ?>
<?php endforeach ?>

HTML: .html

HTML 模板始终以原样打印。不进行进一步处理。

members.html
<h1>Members</h1>
<ul>
    <li>Alice</li>
    <li>Bob</li>
    <li>Carol</li>
</ul>

数据

数据可以通过模板中的简单 变量(例如,$foo)访问,其中变量名对应于分配的数组键或属性。

<h1>Hello, <?= $username ?>!</h1>

分配数据

有几种方法可以将数据分配给模板框

// via assign(…)
$welcome->assign([ "username" => "eve" ]);

// via object property
$welcome->username = "eve";

// via render(…)
$welcome->render([ "username" => "eve" ]);

// implicitly
$welcome([ "username" => "eve" ]);

共享数据

通常,模板框彼此隔离。分配给一个框的数据在另一个框中不可见。

$welcome->username = "eve";          // not accessible to 'profile'
$profile->email = "eve@example.com"; // not accessible to 'welcome'

如果它们应该共享数据,则可以 链接 它们

$welcome->link($profile);

现在,这些模板框已链接,它们共享相同的数据。

welcome.php
<h1>Hello, <?= $username ?>!</h1>
<p>Your email address is: <code><?= $email ?></code></p>
profile.php
<h1>Profile</h1>
<ul>
    <li>Username: <strong><?= $username ?></strong></li>
    <li>Email: <strong><?= $email ?></strong></li>
</ul>

请注意,welcome.php 打印出 $email,它最初分配给 $profile,而 profile.php 输出 $username,尽管它分配给 $welcome

ℹ️ 技巧: 您可以使用现有的 Box 对象(而不是使用 BoxFactory 对象)通过 $box->create('template') 创建模板框,这的好处是 默认链接两个框

默认值

有时提供 默认值 来打印未分配的变量可能很有用。您可以使用 PHP 7 的 空合并运算符?? 轻松实现。

<title><?= $title ?? "Default" ?></title>

转义

转义是一种数据过滤形式,在输出为 HTML 之前对不安全、用户提供的输入进行清理。

endobox提供了两个快捷方式来访问htmlspecialchars()函数:$escape()及其简写版本$e()

<h1>Hello, <?= $escape($username) ?>!</h1>

<h1>Hello, <?= $e($username) ?>!</h1>
转义HTML属性

⚠️ 警告:始终使用双引号包围包含转义变量的HTML属性非常重要,否则您的模板仍然容易受到注入攻击(例如,XSS)。

<!-- Good -->
<img src="portrait.jpg" alt="<?= $e($name) ?>">

<!-- BAD -->
<img src="portrait.jpg" alt='<?= $e($name) ?>'>

<!-- BAD -->
<img src="portrait.jpg" alt=<?= $e($name) ?>>

链式调用 & 嵌套

由于您很少只处理单个模板,您可能正在寻找一种将多个模板有意义地组合在一起的方法。

链式操作

通过链式操作,我们的意思是不进行渲染而连接模板。

链式操作两个模板就像这样简单

$header($article);

现在,对$header$article中的任何一个调用->render()都会渲染这两个模板并返回连接的结果。

ℹ️ 小贴士:无需立即将模板渲染为字符串的好处是灵活性:您可以在知道模板变量的具体值之前定义由模板组成的布局。

链式操作多个模板的一般语法很简单

$first($second)($third)($fourth); // and so on

很好。

更明确(且严格等价)的形式是使用append()prepend(),如下所示

$first->append($second)->append($third)->append($fourth);

或者...

$fourth->prepend($third)->prepend($second)->prepend($first);

ℹ️ 小贴士:请注意,之前看到的Box::__invoke()只是Box::append()的一个别名。

您已经看到了如何将Box对象连接在一起(或添加到前面)。

但是请注意,变量$first$second$third$fourth都是Box类型的对象,这意味着它们需要在某个时刻“复活”——可能使用在最初创建的BoxFactory对象(在这个文档中我们将其称为$endobox)。

换句话说,完整的代码可能看起来像这样

$first = $endobox('first');
$second = $endobox('second');
$third = $endobox('third');

echo $first($second)($third);

实际上,有一种方法可以避免这种样板代码:您可以直接将模板名称(一个string)传递给append()方法,而不是传递Box对象!

所以,您可以这样写

echo $endobox('first')('second')('third');

这看起来很 trivial,但实际上有很多内容。更冗长的形式如下

echo $endobox->create('first')->append('second')->append('third');

这实际上等同于以下行

echo ($_ = $endobox->create('first'))
        ->append($endobox->create('second')->link($_))
        ->append($endobox->create('third')->link($_));

请注意,与之前不同,这些(隐式创建的)盒子现在都自动连接在一起,这意味着它们共享相同的数据。

一般来说:从其他盒子创建的盒子默认是连接的。

嵌套

另一种相当不同的方法(可能是模板设计者而不是开发者的方法)是定义某种类型的布局模板

layout.php
<html>
<head></head>
<body>
<header><?= $header ?></header>
<article><?= $article ?></article>
<footer><?= $footer ?></footer>

然后在控制器中某个地方

$layout = $endobox('layout');
$header = $endobox('header');   // header.html
$article = $endobox('article'); // article.php
$footer = $endobox('footer');   // footer.html

echo $layout->render([
    'header' => $header,
    'article' => $article->assign([ 'title' => "How to make Lasagna" ]),
    'footer' => $footer
]);

这应该没问题,但我们在这里可以删除一些样板代码:实际上$header$footer并不需要成为变量。

这就是嵌套发挥作用的地方!

使用$box()函数在另一个模板中实例化模板Box

layout.php
<html>
<head></head>
<body>
<header><?= $box('header') ?></header>
<article><?= $article ?></article>
<footer><?= $box('footer') ?></footer>

然后简单地...

echo $endobox('layout')->render([
    'article' => $endobox('article')->assign([ 'title' => "How to make Lasagna" ])
]);

这已经变得非常简洁,但它还可以更简洁:通过使用$box()在另一个模板中嵌套模板Box,这两个盒子将默认连接在一起!

这使得我们可以进一步缩减。看看这个

layout.php
<html>
<head></head>
<body>
<header><?= $box('header') ?></header>
<article><?= $box('article') ?></article>
<footer><?= $box('footer') ?></footer>

现在,所有三个模板都是使用$box()嵌套的,因此连接到它们的父级(即$layout)。

这使我们的控制器代码缩减到一行

echo $endobox('layout')->render([ 'title' => "How to make Lasagna" ]);

请注意,尽管实际的$title变量出现在嵌套的article模板中,我们还是为layout模板分配了一个标题。

ℹ️ 小贴士: $box() 函数也作为 Box 对象的方法可用(即,在模板外部):您可以使用 $box->create('template') 实例化新的盒子,其中 $box 是某个已创建的 Box 对象。

函数

函数是向模板添加可重用功能的一种酷炫且方便的方法(例如,过滤器、URL 构建器…)。

注册函数

您可以通过将其分配给模板 Box(就像数据一样)来注册自己的自定义函数(即,闭包)。

以下是一个简单的函数 $day(),它返回星期几

$calendar->day = function () { return date('l'); };

在您的模板文件中,您可以像使用任何变量一样使用它

<p>Today is <?= $day ?>.</p>

它看起来可能像这样(至少有时是这样)

<p>Today is Tuesday.</p>

您甚至可以进一步调用变量,就像调用任何函数一样,并实际上 传递一些参数

以下是一个简单的闭包 $a(),它将一些文本包裹在超链接标签中

$profile->a = function ($text, $href) {
    return sprintf('<a href="%s">%s</a>',
            htmlspecialchars($href),
            htmlspecialchars($text));
};

在您的模板中调用此函数将看起来像这样

<p>Follow me on <?= $a("GitHub", "https://github.com/younishd") ?></p>

这将产生类似这样的结果

<p>Follow me on <a href="https://github.com/younishd">GitHub</a></p>

默认函数

有一些默认的辅助函数可以立即使用(其中一些您可能已经见过)

函数 描述 示例
$box()$b() 在另一个模板中实例化一个 Box。 (参见 嵌套。) <article><?= $box('article') ?></article>
$markdown()$m() 将文本渲染为 Markdown。当文本是用户输入/存储在数据库中时非常有用。 <?= $markdown('这是些 _疯狂评论_!') ?>
$escape()$e() 使用 htmlspecialchars() 清理不安全用户输入。 (参见 转义。) <img src="portrait.jpg" alt="<?= $e($name) ?>">

克隆

您可以使用内置的 clone 关键字轻松克隆模板 Box

$sheep = $endobox('sheep');

$cloned = clone $sheep;

克隆的盒子将具有与原始盒子相同的内容和数据。然而,链式或链接的盒子将被丢弃。

许可证

endobox 是开源软件,受 MIT 许可证 许可。