【问题标题】:super-light templating system in PHP that doesn't allow php code inside templates or use evalPHP 中的超轻模板系统,不允许在模板中使用 php 代码或使用 eval
【发布时间】:2011-08-11 18:45:27
【问题描述】:

我正在寻找一个非常基本的 PHP 模板系统。现在我正在使用:

/**
 * Renders a single line. Looks for {{ var }}
 *
 * @param string $string
 * @param array $parameters
 *
 * @return string
 */
function renderString($string, array $parameters)
{
    $replacer = function ($match) use ($parameters)
    {
        return isset($parameters[$match[1]]) ? $parameters[$match[1]] : $match[0];
    };

    return preg_replace_callback('/{{\s*(.+?)\s*}}/', $replacer, $string);
}

(来自这里:PHP - Extremely light templating system

但我只能分配和显示变量。我还需要一种方法来使用 IF 和循环数组等条件。

我找到了 Rain TPL - http://www.raintpl.com/Quick-Start/#if - 这与我正在寻找的内容非常接近,但有一些我不喜欢它的地方:

  • 它允许正在编写模板的家伙运行 PHP 函数(在 IF 条件内)。
  • 它会写入缓存和 php 文件,这是我不想要的

那么,有没有与此类似但更“基本”、更严格、更安全的东西?

【问题讨论】:

  • 也许您可以详细说明为什么您不想要任何缓存?你的需求有点矛盾。因为你想要 if 子句和东西,所以编译或多或少是要走的路,如果你想走得快。人们建议的 Twig 是一个很好的选择。
  • 为什么要放弃缓存的速度优势?

标签: php parsing templates template-engine


【解决方案1】:

Twig 可能适合你。

它可以做条件,并且对不受信任的代码有沙盒模式。

它进行编译和缓存,但似乎可以关闭。

【讨论】:

  • 但在 Twig 中被使用 eval.
  • @OZ_:如果你关闭缓存,是的。使用 eval 是否有问题?
  • @nikic,阅读问题的标题。我也不喜欢eval
  • @OZ_ Twig 有一个沙盒模式,它不允许允许任意执行代码。
  • 即使在非沙盒模式下,它也只允许非常有限的操作。例如,在标准配置中无法调用普通的 PHP 函数。
【解决方案2】:

还有一个用于 PHP 的 Mustache 端口。 PHP 端口is here。语法类似于您已经在做的,并且支持简单的 IF 和 FOREACH 类型的循环。

而且,不用 eval 就可以了。

【讨论】:

  • 可以推荐 Mustache,这项工作是否可能有轻微的空白/换行问题,但在运行时很容易处理。
【解决方案3】:

【讨论】:

    【解决方案4】:

    根据您的要求,我猜您希望您的网站用户编写一些基本的 php 脚本。您可能找不到可以执行此操作的免费模板引擎。

    我认为根据需要更改现有模板引擎对你来说会更好。

    您可以更改 Rain TPL 以禁用其中一些您不想要的功能。例如你可以这样做......

    1. 在 IF 语句中禁用函数:
      一种。定位elseif( preg_match( '/\{if(?: condition){0,1}="([^"]*)"\}/', $html, $code ) ){

      湾。用类似$this->ifcondition_function_check( $tag );的新方法替换$this->function_check( $tag );

      C。创建将禁用 IF 语句中所有函数的新方法。

      private function ifcondition_function_check($code)
      {
          $preg = '/[a-zA-z0-9]+\((.*?)\)/';
          if (preg_match( $preg, $code, $match ) ){
              // find the line of the error
              $line = 0;
              $rows=explode("\n",$this->tpl['source']);
              while( !strpos($rows[$line],$code) )
                      $line++;
      
              // draw the error line
              $error = str_replace( array('<','>'), array( '&lt;','&gt;' ), array($code,$rows[$line]) );
              $error = str_replace( $code, "<font color=red>$code</font>", $rows[$line] );
      
              // debug the error and stop the execution of the script
              die( "<div>RainTPL Sandbox Error in template <b>{$this->tpl['tpl_filename']}</b> at line $line : <i>$error</i></b>" );
          }
      }
      

      d。现在功能被禁用了。

      1. 删除缓存文件。 (Rain TPL 中的缓存文件是一个 PHP 文件,模板标签被 PHP 代码替换)
        一种。转到方法draw()
        湾。定位unset( $this-&gt;tpl );
        C。在此行之前删除已编译的(缓存)文件@unlink($this-&gt;tpl['compiled_filename']);
        d。现在缓存文件只是执行 PHP 代码的临时文件。

    希望对你有帮助

    【讨论】:

      【解决方案5】:

      非常好用

      http://www.smarty.net/

      【讨论】:

      • 我必须给 Smarty 模板 +1。它们提供了各种深度的功能,但您可以非常愚蠢对待它们,只使用基本的模板需求。它支持条件和循环,您可以关闭缓存。
      • 有一种更好、更快、更先进、与 Smarty 兼容的现代替代方案,称为 Dwoo
      【解决方案6】:

      如果您希望它真正小巧灵活,也许最好的办法就是保留您自己的东西?我喜欢手工制作;-) 您可以扩展您现有的功能。接下来,您的函数加上 ifloop 语句以及为安全起见对变量进行转义:

      <?php
      function renderString($str, $parms)
      {
          // if
          $str = preg_replace_callback('/{{if (?P<name>\w+)}}(?P<inner>.*?){{endif}}/is', function($match) use ($parms) {
              if( isset($parms[$match['name']])) {
                  // recursive
                  return renderString($match['inner'], $parms);
              }
          }, $str);
          // loop
          $str = preg_replace_callback('/{{loop (?P<name>\w+)}}(?P<inner>.*?){{endloop}}/is', function($match) use ($parms) {
              if( isset($parms[$match['name']]) && is_array($parms[$match['name']])) {
                  $str = '';
                  foreach ($parms[$match['name']] as $value) {
                      $parms['loop'] = $value;
                      // recursive
                      $str .= renderString($match['inner'], $parms);
                  }
                  return $str;
              }
          }, $str);
          // var
          $str = preg_replace_callback('/{{(?P<name>\w+)}}/is', function($match) use ($parms) {
              if( isset($parms[$match['name']])) {
                  return htmlspecialchars($parms[$match['name']]);
              }
          }, $str);
          return $str;
      }
      
      $template = "<h1>{{title}}</h1>
      
      {{if optional}}
      <p>Optional: {{optional}}</p>
      {{endif}}
      
      {{if noop}}I'm not there{{endif}}
      
      <ul>
      {{loop numbers}}
      <li>{{symbol}} {{loop}}</li>
      {{endloop}}
      </ul>";
      
      echo renderString($template, array(
          'title'    => 'The Title',
          'optional' => 'I am optional',
          'numbers'  => array( 'one', 'two', 'three'),
          'symbol'   => '>',
      ));
      

      此脚本在 PHP 5.3 中测试,您可以将其 1:1 复制到文件中以使用它。

      【讨论】:

        【解决方案7】:

        试试 PHPTAL:http://phptal.org/

        TAL 模板的语法不会破坏 html,因此您和设计师可以检查它们是否看起来不错。

        另请参阅:
        http://wiki.zope.org/ZPT/TALSpecification14
        http://wiki.zope.org/ZPT/TAL

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-02
          相关资源
          最近更新 更多