【问题标题】:using a loop in a template在模板中使用循环
【发布时间】:2009-08-18 10:06:45
【问题描述】:

我开始编写自己的小型框架,并且我已经了解了它的模板部分。到目前为止,我已经能够用以下代码替换简单的变量:

public function view($page, $vars)
{
    if(!file_exists('system/views/' . $page . '.php'))
    {
        trigger_error("No Template found", E_USER_ERROR);
    }

    $tempArray = file_get_contents('system/views/' . $page . '.php');

    foreach($vars as $key => $value)
    {
        $tempArray = str_replace('{' . $key . '}', $value, $tempArray);
    }

    print $tempArray;
    unset($tempArray);
}

这很好用,但我现在正在寻找的是,如果我想循环显示来自数据库的未知数量的记录,我尝试了一些想法,但到目前为止似乎都没有奏效

【问题讨论】:

  • 有很多开源的 PHP 模板语言,你为什么不看看其中的一种?

标签: php templating


【解决方案1】:

首先,你应该重新考虑你的变量重写。当您的方法之间存在一些依赖关系时,有几种情况不会按预期结束。此外,无论变量是否处于循环中,所有内容都会被替换。

如果你想要类似 {while(condition)}code{/while} 的东西,你需要知道递归也是可能的,因此它不像匹配一个正则表达式那么简单。

一个简单的方法如下:

  • 找到一个标记(变量、whileloop)的开始并记住找到它的位置
  • 如果它是一个变量并且您在最外层范围内(不在循环中),请通过替换来处理它。调整您的指针,这样您就不会在之后阅读替换内容,以避免替换您不想替换的内容。
  • 如果是循环
    • 提取括号之间的条件并将其存储在某个地方
    • 另外,存储当前位置
    • 将令牌压入堆栈以记住当前的递归级别。
    • 遇到 {/while} 标记时从堆栈中移除一个标记。
    • 现在递归进行,将所有嵌套循环标记压入堆栈并在它们结束时将其删除。再次到达最外层时停止。
    • 评估循环的条件。只要它为真,就从起始标记和结束标记之间的源文本创建新副本,并使用递归处理它们。
    • 连接中间结果并用此连接替换从 {while} 到 {/while} 的所有内容。调整你的指针,让你指向循环之后并继续:)

希望这会有所帮助。我知道这听起来有点痛苦,但是如果你理解了这个概念,你应该能够做到(虽然它不是超级高效并且编译像 smarty 这样的模板引擎总是会提前,因为它们只解析一次模板文件并将其编译为 PHP 代码)。

@Daff:您可以使用正则表达式找到标记,但是由于递归,使用一个正则表达式匹配整个循环构造不起作用(除非您的正则表达式具有递归扩展名)。

【讨论】:

  • 迟到的回复我知道,但我想我会让你知道这确实有很大帮助,谢谢!
【解决方案2】:

正如 Zed 已经说过的,PHP 有很多模板语言,最流行的一种是Smarty,我不知道除了学习目的之外重新发明轮子是否真的有意义。您想要做的循环实际上比替换元素要复杂得多。我很确定你可以用很多正则表达式来做到这一点,但在某些时候你最终会编写自己的脚本语言(就像聪明人所做的那样)解析你的视图文件,创建一个语法树,评估它并将其编译为一个新的 PHP 文件。这是相当复杂的,所以我建议要么使用现有的模板引擎,要么使用 PHP 作为模板语言本身(如果严格遵循 MVC 模式,即使有很多讨论也可能有效)。

使用正则表达式,您可以解析 {for ...}{/for} 之间的所有内容以访问具有给定变量名称的项目,其中在 {for 和 } 之后定义变量出现,之后 } 和之前 { /for} 你的 html 定义。这就像一个 foreach 循环,你甚至不能相互嵌套。

{for item=$varname}
    <p>{item.othervalue}</p>
{/for}

【讨论】:

  • 我这样做主要是为了学习,肯定有一些方法可以做到不涉及到那样的极端?
  • 我添加了一个小例子。但是,如果您想真正学习它,您可能想走一个极端……最简单的方法是使用 PHP 作为您的模板语言,或者使用创建自己的模板引擎的极端语言。
  • 感谢您的示例,这似乎是我正在寻找的路线
【解决方案3】:

如果你渴望学习这个(就像我一样),你可以去http://net.tutsplus.com/tutorials/php/roll-your-own-templating-system-in-php-new-premium-tutorial/ - 这是一个关于这个的教程,但是你需要成为会员才能阅读它:)

【讨论】:

    猜你喜欢
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    相关资源
    最近更新 更多