0

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

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

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

4

3 回答 3

1

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

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

{for item=$varname}
    <p>{item.othervalue}</p>
{/for}
于 2009-08-18T10:53:00.613 回答
1

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

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

一个简单的方法如下:

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

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

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

于 2009-08-18T12:04:12.733 回答
0

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

于 2011-02-26T15:48:34.560 回答