2

我正在用 PHP 编写一个数据提供程序类,以帮助我加快多行 SQL 查询结果的呈现速度。基本上,该类有一堆与 SQL 相关的属性和方法来帮助分页、排序和最终呈现数据。至于后者,我希望能够轻松地对行进行模板化,因此我编写了一个名为 render() 的方法,可以使用行模板文件作为参数从视图文件(在 MVC 模型中)调用该方法。它看起来类似于:

public function render($row_template_file) {
    if($result = mysql_query($this->query)) {
        while($row = mysql_fetch_array($result)) {
            include $row_template_file;
        }
    }
}

实际的方法比这更复杂(它检查模板文件是否存在,使用数据抽象类而不是 mysql_* 函数等),但你明白了。行模板文件基本上是直接输出的 HTML,即:

<div class="row">
    <div class="foo"><?php echo $row['foo']; ?></div>
    <div class="bar"><?php echo $row['bar']; ?></div>
</div>

这种方法效果很好,唯一的问题是循环中的 include() 在性能方面不是一个好主意,尤其是在渲染大量行时。在保持以这种方式对行进行模板化的能力的同时,有什么可以替换它的吗?这里几乎没有类似的问题,但所有建议的解决方案都涉及将逻辑与演示混合,这是我想要避免的。我想在第一次迭代期间创建一个匿名函数,然后在所有后续迭代中调用它,但也许我想多了,或者在这里重新发明了轮子。有任何想法吗?

4

5 回答 5

1

printf()/建议的sprintf()解决方案很简洁,但不允许在模板中包含特定于表示的逻辑,例如:

<div class="gender">
    <?php if($row['gender'] == 'f') : ?>
    <img src="female_icon.gif" />
    <?php else : ?>
    <img src="male_icon.gif" />
    <?php endif; ?>
</div>

我知道,我不应该把模板写成“基本上是 HTML” :-)

我一直在使用我在问题中提到的匿名函数解决方案,尽管它看起来不是很漂亮,但它可以工作并且比多个包含要快得多,所以我将其添加为可能的答案之一:

public function render($row_template_file) {
    if($result = mysql_query($this->query)) {
        $render_row = create_function('$row', '?>'.file_get_contents($row_template_file).'<?php ');
        while($row = mysql_fetch_array($result)) {
            $render_row($row);
        }
    }
}
于 2012-04-18T20:12:56.793 回答
1

也许改用 php 的 printf() / sprintf()函数?

因此,您的模板文件将包含如下代码:

<div class="row">
    <div class="foo">%s</div>
    <div class="bar">%s</div>
</div>

在循环之前,您只需将其加载到变量中一次:

$tmpl = file_get_contents( $row_template_file);

在循环中,您只需将变量放入模板中:

printf( $tmpl, $row['foo'], $row['bar']);

请参阅上面链接中的示例 #3 和 #4,了解“参数交换”——在模板中使用编号位置的方法——不必担心不同模板中参数的不同顺序。

希望这对你有用。

于 2012-04-18T11:44:55.863 回答
0

可以尝试使用 eval 函数。对 php.net 的评论可能会对您有所帮助: http ://www.php.net/manual/ru/function.eval.php#108091

于 2012-04-19T08:03:30.700 回答
0

这几乎感觉像是一个太简单的解决方案,也许我只是不明白什么是大问题,但是使用 PHP 函数呢?

function outputRow($row) {
    echo '<div class="row">';
    echo '<div class="foo">' . $row['foo'] . '</div>';
    echo '<div class="bar">' . $row['bar'] . '</div>';
    echo '</div>';
}

而不是包括,你打电话outputRow($row)

于 2012-04-18T11:41:39.697 回答
0

将模板创建为带有占位符的字符串并将值替换到其中。将其传递给render()方法。

然后,您只需要决定如何最好地获取字符串 - 通过file_get_contents(我会这样做)或简单地将其硬编码到某个“模板”类中,从中提取一个接口 -并传递它。

于 2012-04-18T11:46:58.570 回答