包含或eval的自定义流包装器?

时间:2012-10-12 09:07:09

标签: php eval template-engine stream-wrapper

概述

我目前正在编写模板引擎。它甚至支持多种“格式”。目前,它可以解析.php个文件和.tpl(特定于此引擎)。

我会给你一个两个例子,只是为了给你一个想法。

的template.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。

template.tpl

Name: {>$name}
Posts: 
{foreach($posts as $post):}
    - {>$post->name} ({=count($post->comments)} comments)
      {=:render('post/shortpost', array('post' => $post))}
{endforeach}

这个模板化的“语言”简单地被翻译成PHP。

作仪

的eval()

目前使用eval()解析这些模板。

  • 我不需要更改任何代码

魂斗罗

  • 当模板中发生错误时,您只会收到无用的错误消息  告诉你错误发生在哪个文件中,有时行号甚至是错误的。
  • 安全?模板文件只需要是可读的吗?
  • 调试代码很困难。
  • 代码难以理解
  • 更多..?

流包装器和include()

我最近在php中读到了关于流包装器的内容。你甚至可以创建自己的。除eval之外的另一个解决方案是为每个模板“format”创建自定义流包装器,并使用include来解析模板。

这有以下(潜在)缺陷:

  • 可以解决在错误消息中显示错误的文件/行号的问题(有人有这方面的体验吗?)
  • 您可以准确地处理模板文件以便如何处理它。完全控制。

魂斗罗

  • allow_url_(fopen|include)必须在吗?
  • 很慢? (eval()也慢了吗?)
  • 没有安全感。 include与eval基本相同。
  • 更多......?

编辑:缓存已解析的文件并包含()

第三个选项是将模板解析为PHP代码并缓存它们(如@ Jen-YaKovalev所建议的那样)。

  • 包括缓存

魂斗罗

  • 如果在包含渲染模板时发生错误并发生错误  错误消息未指向正确的文件/最终显示您  错误的行号。
  • 您需要一个额外的tmp/目录来保存已解析的文件。你需要写  PHP / webserver的权限。因为黑客会更加不安全  会更容易添加一些恶意代码。

编辑:流过滤器和include('php:// filter')

最近发现了以下php.net页面:

这将是解决此问题的另一种可能性。使用include('php://filter/read=filtername/resource=file.php'),我可以在执行之前包含一个首先通过过滤器filtername的文件。

  • 不需要像流包装器那样多的代码

魂斗罗

  • 与流包装器(缓存?)没有那么多可能性。
  • 安全?
  • 速度

问题

  • 是否有使用流包装器来解析模板文件或类似文件的经验?
  • 还有其他解决方案吗?
  • 还有更多的专业和反对意见吗?
  • 你会推荐哪一个?

2 个答案:

答案 0 :(得分:1)

我认为这只是一种编码风格的味道,你最好投票一下。

  • 我个人认为 eval是邪恶的(在每种语言中),
  • 使用include + php包装器(甚至是集成的*),
  • 知道所有大型(gish)模板系统都使用编译到一个php文件(smarty,twig),这就是我要使用的那个。

(*)在早期的项目中,我们在data-url包装的包含中使用了1行代码(空类扩展),其性能非常糟糕。

答案 1 :(得分:0)

您当然不希望在生产环境中的每个请求中解析模板,这将浪费资源,因此是一种缓慢而不是非常智能的方法,所以我强烈建议使用缓存已解析的文件和include()方法。