mschop / noteephp
Requires
- php: >=7.0
- vdb/uri: ~0.2
Requires (Dev)
- humbug/humbug: dev-master
- phpunit/phpunit: ~4.8
- satooshi/php-coveralls: ~2.0
This package is auto-updated.
Last update: 2019-09-16 09:54:06 UTC
README
PHP HTML生成库。
什么是NoTeePHP
NoTeePHP是一个专注于安全和正确性的模板引擎替代品。
NoTeePHP的优势
- 更安全
- 错误更少
- 更容易设置(无需编译步骤)
- 可调试
- 可测试
- 不可变节点树(无限节点重用)
- 注册事件
设置
使用composer安装NoTeePHP。
composer install mschop/noteephp
就这样。
基本用法
这是一个简单的例子
$nf = new NodeFactory(new DefaultEscaper('utf-8'), new UriValidator());
function getItems use ($nf)()
{
$result = [];
for($x = 1; $x < 10; $x++) {
$result[] = $nf->li('item ' . $x);
}
return $result;
}
$root = $nf->div(
['class' => 'a b c'],
$nf->abbr(
['title' => 'hypertext markup language'],
'html'
),
$nf->ul(
$nf->li('item 0'),
getItems()
)
);
echo($root);
这将产生以下结果
<div class="a b c">
<abbr title="hypertext markup language">html</abbr>
<ul>
<li>item 0</li>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
<li>item 6</li>
<li>item 7</li>
<li>item 8</li>
</ul>
</div>
安全
许多模板引擎默认不提供转义。开发者必须记住在模板中使用的每个信息都要进行转义。问题是开发者100次都正确转义,然后会忘记一次。NoTeePHP默认提供转义。
其他模板引擎如Twig默认提供转义。但在Twig中,在某些特殊情况下也可能存在XSS漏洞。想象一下,你想要创建一个以动态值开始的锚点。一个天真的开发者可能会认为依赖于Twigs的转义就足够了
<a href="{{ user.name }}">click me</a>
现在攻击者可以创建一个用户名为"javascript:alert(1)"的账户,你就有了漏洞。
NoTeePHP创建一个对象树而不是连接字符串。因此它知道变量在什么上下文中使用,因此可以使用适当的转义或对变量进行额外的验证。
错误更少
语法错误会导致你的应用中难以发现的bug。使用NoTeePHP,你将不会遇到这样的问题。不再有包含标签错误或缺失引号。总是得到格式良好的HTML。
调试
模板引擎将模板编译为纯PHP。这个PHP通常很难阅读,因此很难调试。使用NoTeePHP,你没有这样的编译步骤。这简化了设置,提高了安全性,并默认启用易于调试。
示例
创建一个NodeFactory
NodeFactory类是NoTeePHP的核心。
// using the right encoding is security relevant
$nf = new NodeFactory(new DefaultEscaper('utf-8'), new UriValidator());
节点创建
$node = $nf->div(
['id' => 'someid'], // optional assoc array, containing all attributes
'some text, that will be escaped',
$nf->raw('some text, that will not be escaped'),
$this->span(), // nodes without children will be self-closing tags -> <span />
[ // children can be passed as arrays for using the result of other methods
$nf->span('text'),
$nf->span('text2')
]
);
echo $node;
事件
如果你需要在某些情况下修改节点树,你可以注册一个订阅者到节点工厂
$nf = new NodeFactory(new DefaultEscaper('utf-8'), new UriValidator());
class CsrfTokenAdder implements SubscriberInterface
{
public function notify(NodeFactory $nodeFactory, DefaultNode $node): DefaultNode
{
if ($node->getTagName() !== 'form') return;
$attributes = $node->getAttributes();
$method = strtolower($attributes['method'] ?? 'get');
$children = $node->getChildren();
if (!isSecure($method)) {
$children[] = $nodeFactory->input(['type' => 'hidden', 'name' => 'csrf_token', 'value' => getCsrfToken()])
}
return new DefaultNode(
$node->getTagName(),
$node->getEscaper(),
$attributes,
$children
);
}
}
$nf->subscribe(new CsrfTokenAdder());
调试
如果你需要知道特定节点从哪里来,为NodeFactory启用调试模式
$nf = new NodeFactory(new DefaultEscaper('utf-8'), new UriValidator(), true);
现在,对于每个生成的HTML节点,都会有一个包含节点源文件和行的属性"data-source"。在生产环境中,你应该禁用调试模式。
简短语法
你也可以使用更短的语法,它依赖于全局状态。由于全局状态很丑,而且通常不建议使用,因此这个功能默认是禁用的。要启用它,你需要手动包含文件global.php
。
global $noTeePHP; // this global variable is require for including global.php
$noTeePHP = new NodeFactory(new DefaultEscaper('utf-8'), new UriValidator());
require '{pathToVendorDir}/mschop/NoTeePHP/global.php';
现在,你可以通过调用函数来创建节点(这更简洁易写)
_div(
['id' => 'some-id'],
_a(['href' => 'https://packagist.org.cn/mschop/NoTeePHP', 'Link to the best lib on the world'])
)