Dag*_*bit 5 html php eval custom-tags
概观
大约2009年底,我写了一个简单的模板系统,在内部我们的设计师手册洁具型网站使用PHP/HTML.该系统的目标是通过PHP处理的自定义标记允许模板化其他纯HTML.例如,模板化页面可能如下所示:
<tt:Page template="templates/main.html">
<tt:Content name="leftColumn">
<p> blah blah </p>
...
</tt:Content>
<tt:Content name="rightColumn">
<p> blah blah </p>
...
</tt:Content>
</tt:Page>
Run Code Online (Sandbox Code Playgroud)
模板本身可能如下所示:
<html>
<head>...</head>
<body>
<div style="float:left; width:45%">
<tt:Container name="leftColumn" />
</div>
<div style="width:45%">
<tt:Container name="rightColumn" />
</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
除了Page和Content/Container标签之外,核心中还包含一些其他标签,用于流控制,迭代集合,输出动态值等.框架的设计使得添加自己的一套很容易.标记在另一个前缀和命名空间下注册
自定义标签到PHP
我们如何解析这些自定义标签?由于无法保证HTML文件是格式良好的XML,因此XSLT/XPATH等解决方案将不可靠.相反,我们使用正则表达式来查找带有已注册前缀的标记,并用PHP代码替换它们.PHP代码是一个基于堆栈的设计...在遇到一个开始标记,表示创建该标记的物体压入堆栈,和它的"初始化函数"(如果有的话)延伸.每当遇到已注册的结束标记时,最新的对象将从堆栈中弹出,并且其"呈现函数"将运行.
因此,该框架替换PHP模板标签后,我们的示例页面看起来像这样(在房地产这有点丑陋):
<?php $tags->push('tt', 'Page', array('template'=>'templates/main.html')); ?>
<?php $tags->push('tt', 'Content', array('name'=>'leftColumn')); ?>
<p> blah blah </p>
...
<?php $tags->pop(); ?>
<?php $tags->push('tt', 'Content', array('name'=>'rightColumn')); ?>
<p> blah blah </p>
...
<?php $tags->pop(); ?>
<?php $tags->pop(); ?>
Run Code Online (Sandbox Code Playgroud)
好的,坏的,和 eval
现在,如何执行我们新生成的PHP代码?我可以在这里想到几个选项.最简单的是简单eval的字符串,这很好用.但是,任何程序员都会告诉你"eval是邪恶的,不要使用它......"所以问题是,有什么比eval我们在这里可以使用的更合适吗?
我考虑使用临时或缓存文件,使用php://输出流等,但据我所知,这些并没有提供任何真正的优势eval.缓存可以加快速度,但实际上我们对这个东西的所有站点已经非常快,所以我认为此时不需要进行速度优化.
问题
对于此列表中的每个事项:这是一个好主意吗?你能想到一个更好的选择吗?
eval(或类似)感谢阅读和TIA的任何建议.:)
让我提倡一种不同的方法。不要动态生成 PHP 代码,然后尝试找出如何安全地执行它,而是在遇到标签时直接执行它。您可以一次处理整个 HTML 块,并在遇到每个标签时立即对其进行处理。
编写一个查找标签的循环。它的基本结构如下所示:
$tags则可能不需要将其保存在任何地方)。$tags->push,只需$tags->push直接调用即可。使用这种方法,您只需直接调用 PHP 函数,而无需即时构建 PHP 代码,然后再执行它。的需要eval已经消失了。
步骤#3 基本上有两种情况。当您遇到开始标签时,您将立即执行push. 然后,当您点击结束标记时,您可以执行 a pop,然后以适当的方式处理该标记,现在您已经处理了自定义元素的全部内容。
以这种方式处理 HTML 也更加高效。对长 HTML 字符串进行多次搜索和替换效率很低,因为每次搜索和每次替换字符串长度的复杂度都是 O( n )。这意味着您一遍又一遍地重复扫描字符串,每次进行替换时,您都必须生成长度相似的全新字符串。如果您有 20KB 的 HTML,则每次替换都需要搜索该 20KB,然后创建一个新的 20KB 字符串。
| 归档时间: |
|
| 查看次数: |
1199 次 |
| 最近记录: |