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

Mar*_*ant 10 php template-engine eval 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 ?>
Run Code Online (Sandbox Code Playgroud)

这基本上只是一个标准的PHP.

template.tpl

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

这种模板化的"语言"简单地被翻译成上面的PHP.

作仪,

的eval()

目前使用这些模板进行解析eval().

  • 我不需要更改任何代码

反对

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

流包装器和include()

我最近阅读了关于php中的流包装器.你甚至可以创建自己的.另一种解决方案eval是为每个模板"格式"创建自定义流包装器,并使用include来解析模板.

这有以下(潜在)缺陷:

  • 可以解决在错误消息中显示错误的文件/行号的问题(有没有人经历过这个?)
  • 你可以准确地处理模板文件如何处理它.完全控制.

反对

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

编辑:缓存解析的文件和包括()

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

  • 包括缓存

反对

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

编辑:流过滤器和包含('php://过滤器')

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

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

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

反对

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

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

poz*_*ozs 1

我认为这只是一个人编码风格的品味,你最好投票什么的。

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

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