概述
我目前正在编写模板引擎。它甚至支持多种“格式”。目前它可以解析.php
文件和.tpl
(特定于这个引擎)。
我会给你一个两者的小例子,只是为了给你一个想法。
模板.php:
Name: <?php echo $this->h($name) ?>
Posts:
<?php foreach($posts as $post): ?>
- <?php echo $this->h($post->name) ?> (<?php echo count($post->comments) ?> comments)
<?php echo $this->render('post/shortpost', array('post' => $post)) ?>
<?php endforeach ?>
这基本上只是一个标准的 PHP。
模板.tpl
Name: {>$name}
Posts:
{foreach($posts as $post):}
- {>$post->name} ({=count($post->comments)} comments)
{=:render('post/shortpost', array('post' => $post))}
{endforeach}
这种模板“语言”简单地被翻译成上面的 PHP。
比较
评估()
目前这些模板是使用eval()
.
临
- 我不必更改任何代码
魂斗罗
- 当模板中发生错误时,您只会收到一条无用的错误消息,它不会告诉您错误发生在哪个文件中,有时行号甚至是错误的。
- 安全?模板文件只需要可读吗?
- 很难调试代码。
- 代码更难理解
- 更多的 .. ?
流包装器和 include()
我最近阅读了 php 中的流包装器。你甚至可以创建自己的。另一个解决方案eval
是为每个模板“格式”创建自定义流包装器并使用 include 来解析模板。
这有以下(潜在的)缺陷:
临
- 可以解决在错误消息中显示错误文件/行号的问题(有没有人遇到过这个问题?)
- 您可以完全按照希望处理的方式处理模板文件。完全控制。
魂斗罗
allow_url_(fopen|include)
必须开启?- 它很慢吗?(也很
eval()
慢?) - 在安全方面没有收获。include 与 eval 的作用基本相同。
- 更多的 ... ?
编辑:缓存的解析文件和 include()
第三种选择是将模板解析为 PHP 代码并缓存它们(如 @Jen-YaKovalev 所建议的那样)。
临
- 包括缓存
魂斗罗
- 如果在包含渲染模板时发生错误并且发生错误,则错误消息不会将您指向正确的文件/最终会显示错误的行号。
- 您需要一个额外的
tmp/
目录来保存已解析的文件。您需要 PHP/webserver 的写入权限。会更不安全,因为黑客会更容易附加一些恶意代码。
编辑:流过滤器和包含('php://filter')
最近发现了以下 php.net 页面:
php://filter:
http://php.net/manual/en/wrappers.php.phpstrea_filter_register
http://fr2.php.net/manual/en/function.stream-filter-register.php
这将是解决此问题的另一种可能性。使用include('php://filter/read=filtername/resource=file.php')
,我可以包含一个filtername
在执行之前首先通过过滤器的文件。
临
- 不需要像流包装器那么多的代码
魂斗罗
- 不像流包装器(缓存?)
- 安全?
- 速度?
问题
- 有使用流包装器解析模板文件或类似文件的经验吗?
- 还有其他解决方案吗?
- 有更多的专业人士和反对者吗?
- 你会推荐哪一个?