简单的PHP模板...如果没有`eval`可以使用吗? [英] Dirt-simple PHP templates... can this work without `eval`?

查看:87
本文介绍了简单的PHP模板...如果没有`eval`可以使用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新-感谢您的所有回复.这个Q有点混乱,所以如果有人感兴趣的话,我开始续集.

Update- Thanks for all the responses. This Q is getting kind of messy, so I started a sequel if anyone's interested.

我当时正在为朋友准备一个快速脚本,偶然发现了一种非常简单的用PHP进行模板制作的方法.

I was throwing together a quick script for a friend and stumbled across a really simple way of doing templating in PHP.

基本上,这个想法是将html文档解析为一个Heredoc字符串,因此PHP中将扩展其中的变量.

Basically, the idea is to parse the html document as a heredoc string, so variables inside of it will be expanded by PHP.

传递函数允许在字符串内进行表达式求值以及函数和静态方法调用:

A passthrough function allows for expression evaluation and function and static method calls within the string:

function passthrough($s){return $s;}
$_="passthrough";

用于解析Heredoc字符串中的文档的代码非常简单:

The code to parse the document inside a heredoc string is ridiculously simple:

$t=file_get_contents('my_template.html');
eval("\$r=<<<_END_OF_FILE_\n$t\_END_OF_FILE_;\n");
echo $r;

唯一的问题是,它使用了eval.

The only problem is, it uses eval.

  • 谁能想到一种无需使用eval却不添加解析器或大量正则表达式疯狂的模板制作方法?

  • Can anyone think of a way to do this sort of templating without using eval, but without adding a parser or a ton of regex madness?

是否有一些建议,如果不编写完整的解析器,就可以逃避不属于PHP变量的流浪美元符号?流浪的美元符号问题是否会使这种方法不适用于严重"使用?

Any suggestions for escaping stray dollar signs that don't belong to PHP variables without writing a full-on parser? Does the stray dollar sign problem render this approach not viable for 'serious' use?

这是一些示例模板HTML代码.

Here's some sample templated HTML code.

<script>var _lang = {$_(json_encode($lang))};</script>
<script src='/blah.js'></script>
<link href='/blah.css' type='text/css' rel='stylesheet'>

<form class="inquiry" method="post" action="process.php" onsubmit="return validate(this)">

  <div class="filter">
    <h2> 
      {$lang['T_FILTER_TITLE']}
    </h2>
    <a href='#{$lang['T_FILTER_ALL']}' onclick='applyFilter();'>
      {$lang['T_FILTER_ALL']}
    </a>
    {$filter_html}
  </div>

  <table class="inventory" id="inventory_table">
    {$table_rows}
    <tr class="static"><th colspan="{$_($cols+1)}">
      {$lang['T_FORM_HELP']}
    </th></tr>
    {$form_fields}
    <tr class="static">
      <td id="validation" class="send" colspan="{$cols}">&nbsp;</td>
      <td colspan="1" class="send"><input type="submit" value="{$lang['T_SEND']}" /></td>
    </tr>
  </table>

</form>

为什么要使用模板?


有人在讨论是否需要在PHP中创建模板层,诚然,模板模板已经很不错了.

Why use templating?


There's been some discussion of whether creating a templating layer is necessary in PHP, which, admittedly, is already pretty good at templating.

一些有用的模板简短原因:

Some quick reasons templating is useful:

  • 您可以控制它

如果在对文件进行解释之前对其进行了预处理,则可以对其进行更多控制.您可以注入内容,锁定权限,抓取恶意php/javascript,对其进行缓存,通过xsl模板运行它,等等.

If you preprocess the file before it goes to the interpreter, you have more control over it. You can inject stuff, lock down permissions, scrape for malicious php / javascript, cache it, run it through an xsl template, whatever.

好的MVC设计

模板化促进了视图与模型和控制器的分离.

Templating promotes separation of view from model and controller.

在视图中跳入和跳出<?php ?>标签时,很容易变得懒惰并执行一些数据库查询或执行一些其他服务器操作.使用上述方法,每个块"只能使用一个语句(不能使用分号),因此要陷入该陷阱要困难得多. <?= ... ?>具有几乎相同的好处,但是...

When jumping in and out of <?php ?> tags in your view, it's easy to get lazy and do some database queries or perform some other server action. Using a method like the above, only one statement may be used per 'block' (no semicolons), so it's much more difficult to get caught in that trap. <?= ... ?> have pretty much the same benefit, but...

并非总是启用短标签

...并且我们希望我们的应用程序可以在各种配置上运行.

...and we want our app to run on various configurations.

当我最初一起构思一个概念时,它最初是一个php文件.但是在它增长之前,除非所有的php文件的开头都只有一个<?php,而结尾只有一个?>,否则我会很不高兴,而且最好是所有类,除了诸如控制器,设置,图像服务器等之类的东西.

When I initially hack a concept together it starts out as one php file. But before it grows I'm not happy unless all php files have only one <?php at the beginning, and one ?> at the end, and preferably all are classes except stuff like the controller, settings, image server, etc.

我根本不需要太多的PHP,因为设计师在Dreamweaver或类似的东西堆满床时会感到困惑:

I don't want much PHP in my views at all, because designers become confused when dreamweaver or whatever poops the bed when it sees something like this:

<a href="<?php $img="$img_server/$row['pic'].png"; echo $img; ?>">
  <img src="<?php echo $img; ?>" /></a>

对于程序员来说,这很难看.一般的平面设计师不会去附近的任何地方.这样的事情更容易解决:

This is hard enough for a programmer to look at. The average graphic designer won't go anywhere near it. Something like this is a much easier to cope with:

<a href="{$img}"><img src="{$img}" /></a>

程序员将自己讨厌的代码保留在html之外,现在,设计师可以发挥自己的设计魔力.是的!

The programmer kept his nasty code out of the html, and now the designer can work his design magic. Yay!

考虑到每个人的建议,我认为对文件进行预处理是必须的方法,并且中间文件应尽可能接近常规的"php模板",并且模板应使用语法糖.当我玩的时候,Eval仍然存在. Heredoc东西已经改变了它的角色.我待会儿会写更多,并尝试回答一些答案,但是现在...

Taking everyone's advice into consideration, I think preprocessing the files is the way to go, and the intermediate files should be as close as normal "php templating" as possible, with the templates being syntactic sugar. Eval still in place for now while I play with it. The heredoc thing has sort of changed its role. I'll write more later and try to respond to some of the answers, but for now...

<?php



class HereTemplate {

  static $loops;

  public function __construct () {
    $loops=array();
  }

  public function passthrough ($v) { return $v; }

  public function parse_markup ($markup, $no_escape=null, $vars=array()) {
    extract($vars);
    $eot='_EOT_'.rand(1,999999).'_EOT_';
    $do='passthrough';
    if (!$no_escape) $markup=preg_replace(
      array(
        '#{?{each.*(\$\w*).*(\$\w*).*(\$\w*).*}}?#', 
        '#{?{each.*(\$\w*).*(\$\w*).*}}?#', 
        '#{?{each}}?#',
        '#{{#', '#}}#',
        '#{_#', '#_}#',
        ),
      array(
        "<?php foreach (\\1 as \\2=>\\3) { ?>", 
        "<?php foreach (\\1 as \\2) { ?>", 
        "<?php } ?>",
        "<?php echo <<<$eot\n{\$this->passthrough(", ")}\n$eot\n ?>",
        "<?php ", " ?>",
        ), 
      $markup);
    ob_start(); 
    eval(" ?>$markup<?php ");
    echo $markup;
    return ob_get_clean();
  }

  public function parse_file ($file) {
    // include $file;
    return $this->parse_markup(file_get_contents($file));
  }

}


// test stuff


$ht = new HereTemplate();
echo $ht->parse_file($argv[1]);


?>

...

<html>

{{each $_SERVER $key $value}

<div id="{{$key}}">

{{!print_r($value)}}

</div>

{each}}



</html>

推荐答案

PHP最初原本是作为模板语言使用的(即一种允许您将代码嵌入HTML的简单方法).

PHP was itself originally intended as a templating language (ie a simple method of allowing you to embed code inside HTML).

从您自己的示例中可以看到,它太复杂了,以至于无法证明在大多数情况下以这种方式使用它是合理的,因此良好实践将其从传统的语言转移到了将其更多地用作传统语言,并且仅打破了<?php ?>标记尽可能少.

As you see from your own examples, it got too complicated to justify being used in this way most of the time, so good practice moved away from that to using it more as a traditional language, and only breaking out of the <?php ?> tags as little as possible.

问题在于人们仍然想要一种模板语言,因此发明了Smarty之类的平台.但是,如果现在来看它们,Smarty支持诸如其自己的变量和foreach循环之类的东西……不久之后,Smarty模板就开始出现与PHP模板相同的问题;您可能还只是刚开始使用本机PHP.

The trouble was that people still wanted a templating language, so platforms like Smarty were invented. But if you look at them now, Smarty supports stuff like its own variables and foreach loops... and before long, Smarty templates start to have the same issues as PHP templates used to have; you may as well just have used native PHP in the first place.

我想在这里说的是,简单的模板语言的理想实际上并没有那么容易实现.要使它既简单又不会吓到设计师,同时又给它足够的灵活性来实际执行您需要做的事情,几乎是不可能的.

What I'm trying to say here is that the ideals of a simple templating language aren't actually that easy to get right. It's virtually impossible to make it both simple enough not to scare off the designers and at the same time give it enough flexibility to actually do what you need it to do.

这篇关于简单的PHP模板...如果没有`eval`可以使用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆