在模板中使用循环

时间:2009-08-18 10:06:46

标签: php templating

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

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);
}

哪个工作正常,但我现在正在寻找的是,如果我想循环显示来自数据库的未知数量的记录,我尝试了一个想法的耦合器,但似乎没有工作到目前为止

3 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

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

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

一种简单的方法如下:

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

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

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

答案 2 :(得分:0)

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