11

概述

我目前正在编写模板引擎。它甚至支持多种“格式”。目前它可以解析.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 页面:

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

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

魂斗罗

  • 不像流包装器(缓存?)
  • 安全?
  • 速度?

问题

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

2 回答 2

1

我认为这只是一个人的编码风格的品味,你最好投票它或其他东西。

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

(*) 在早期的项目中,我们在数据 url包装的包含中使用了 1 行代码(一个空的类扩展),它的性能很糟糕。

于 2012-10-21T17:02:23.853 回答
0

您当然不想在生产环境中的每个请求都解析模板,这会浪费资源,因此是一种缓慢且不是非常聪明的方法,因此我强烈建议使用缓存的解析文件并包含( )方法。

于 2012-10-21T21:46:54.650 回答