mschop/noteephp

该包已被废弃,不再维护。作者建议使用mschop/notee包。

HTML生成库

维护者

详细信息

gitlab.com/mschop/noteephp

安装: 414

依赖: 0

建议者: 0

安全: 0

星标: 0

分支: 0

v1.1.2 2017-09-29 16:52 UTC

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'])
)