【问题标题】:In PHP is there a better way to do dynamic templating在 PHP 中有没有更好的方法来做动态模板
【发布时间】:2019-12-09 12:13:07
【问题描述】:

我正在为一个应用程序创建模块,该模块将具有简单的自定义模板,其中包含将被数据库中的数据替换的标签。此模块的每个实例中的字段名称将不同。我想知道是否有更好的方法来做到这一点。

下面的代码是我想出的,但我相信一定有更好的方法。我在 preg_split 和 preg_match_all 上苦苦挣扎,刚刚达到了我的极限,所以我以愚蠢的方式做到了。

<?php

$customTemplate = "
<div>
    <<This>>
    <<that>>
</div>
";

function process_template ($template, $begin = '<<', $end = '>>') {
    $begin_exploded = explode($begin, $template);
    if (is_array($begin_exploded)) {
        foreach ($begin_exploded as $key1 => $value1) {
            $end_exploded = explode($end, $value1);

            if (is_array($end_exploded)) {
                foreach ($end_exploded as $key2 => $value2) {
                    $tag = $begin.$value2.$end;
                    $variable = trim($value2);

                    $find_it = strpos($template,$tag);
                    if ($find_it !== false) {
                        //str_replace ($tag, $MyClass->get($variable), $template );
                        $template = str_replace ($tag, $variable, $template);
                    }
                }
            }
        }
    }
    return $template;
}


echo(process_template($customTemplate));

/* Will Echo 

<div>
    This
    that
</div>

*/
?>

以后我会连接 $MyClass->get() 来用正确的数据替换标签。并且自定义模板将由用户构建。

【问题讨论】:

  • 有php模板引擎,不用自己写,
  • 更不用说,php 本身就是一种简单的模板语言。如果您将逻辑与视图分离,那么剩下的就是循环和打印变量。您的视图可能(应该?)都是 html,只有 php 是单行的,例如 &lt;?php while($row=$someObj-&gt;nextRow(): ?&gt;&lt;li&gt;&lt;?= $row-&gt;varName ?&gt;&lt;/li&gt;
  • twig.symfony.comlaravel.com/docs/5.8/blade。在他们那里。
  • 注意explode()总是返回一个数组,两个is_array()测试是不需要的。
  • @TimMorton 我不希望用户必须了解任何关于 php 的知识才能将变量添加到模板,只需简单的可识别标签。谢谢您的意见。我会考虑的。

标签: php regex str-replace explode templating


【解决方案1】:

我宁愿使用preg_replace_callback,而不是preg_splitpreg_match,因为你正在做替换,替换值是从看起来最终会成为另一个类中的方法派生的。

function process_template($template, $begin = '<<', $end = '>>') {
    // get $MyClass in the function scope somehow. Maybe pass it as another parameter?
    return preg_replace_callback("/$begin(\w+)$end/", function($var) use ($MyClass) {
        return $MyClass->get($var[1]);
    }, $template);
}

这里有一个例子:https://3v4l.org/N1p03

我认为这只是为了好玩/学习。如果我真的需要使用模板来做某事,我宁愿从composer require "twig/twig:^2.0" 开始。事实上,如果你有兴趣了解更多关于它是如何工作的,你可以去看看一个成熟的系统,比如 twig 或 Blade。 (Better than I've done it in this answer.)

【讨论】:

  • 不,这不仅仅是为了娱乐/学习。我想学习 twig 和 laravel 以及其他所有框架。但我是一名预算开发人员,正在开发预算 wordpress 海狸构建器自定义模块。
  • 谢谢,一旦我的逻辑完成,这看起来会是更好的处理方式。谢谢楼主!
【解决方案2】:

周围有大量的模板引擎,但有时……只是为一件简单的事情增加复杂性和依赖关系。这是我用于进行一些 javascript 更正的修改示例。这适用于您的模板。

function process_template($html,$b='<<',$e='>>'){
    $replace=['this'=>'<input name="this" />','that'=>'<input name="that" />'];
    if(preg_match_all('/('.$b.')(.*?)('.$e.')/is',$html,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE)){
      $t='';$o=0;
      foreach($matches as $m){
        //for reference $m[1][0] contains $b, $m[2][0] contains $e
        $t.=substr($html,$o,$m[0][1]-$o);
        $t.=$replace[$m[2][0]];
        $o=$m[3][1]+strlen($m[3][0]);
      }
      $t.=substr($html,$o);
      $html=$t;
    }
    return $html;
}
$html="
<div>
    <<this>>
    <<that>>
</div>
";
$new=process_template($html);
echo $new;

出于演示目的,我放置了处理替换的数组$replace。您将那些替换为您将处理替换的函数。

这是一个有效的 sn-p:https://3v4l.org/MBnbR

我喜欢这个功能,因为您可以控制要替换的内容以及要放回最终结果的内容。顺便说一句,使用PREG_OFFSET_CAPTURE 还可以在匹配项上返回正则表达式组发生的位置。这些在$m[x][1] 上。捕获的文本将位于$m[x][0]

【讨论】:

  • “只是为一件可能很简单的事情添加复杂性和依赖关系”人们往往会发现这种“复杂性和依赖关系”实际上最终会成为“边缘情况已经被广泛使用、经过良好测试的代码”发现并解决”。 en.wikipedia.org/wiki/Reinventing_the_wheel
  • 感谢理解。我确实想学习这些其他框架。在我学会它们之前,我真的不知道它会给这个小项目增加多少时间和复杂性。谢谢你的解决方案!
  • @ceejayoz 我同意你的观点,我应该更加谨慎地看待这个陈述,特别是对于那些正在学习它的人。我有超过 30 年的编码经验,我目前的角色是代码优化,而不会在裸机上受到影响。但我也看到初级程序员陷入了恐怖依赖兔子洞。这不是重新发明轮子,而是添加更多你需要的轮子。 Zrux,我建议您不仅要学习如何使用框架,还要最终了解它的工作原理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-22
相关资源
最近更新 更多