奇技淫巧 - 阅读主题
<<  <  1  >  >>

优化php嵌套模版

好(0) 差(0) 阅读(3843) 评论(2)
Wen 给 Wen 发消息 给 Wen 发email
poster face
等级:◆◆◆◆◇◇


用PHPLIB提供的模版类(class Template)可以非常方便地制作页面和程序分离的php应用。页面和程序的分离大大增强了代码的可读性和管理的方便性,并使得工作可以划分给美工人员和程序员分别完成,分工十分明确。

灵活使用模版类可以产生各种各样的特殊效果,例如使用嵌套模版可以输出二维的数据表,或者其它具有二维特性的数据。例如输出一个九九乘法表,可以用以下两个文件实现:

nine.tpl文件:

<html>
<head>
<title>九九乘法表</title>
</head>
<body>
<table>
    <!-- BEGIN bloRow -->
    <tr>
        <!-- BEGIN bloCol{row_num} -->
        <td>{grid_value}</td>
        <!-- END bloCol{row_num} -->
    </tr>
    <!-- END bloRow -->
</table>
</body>
</html>

nine.php文件:

<?php
// 包含PHPLIB的模版类文件
require_once("template.inc");

// 创建模版实例并打开模版文件
$objTmplt = new Template();
$objTmplt->set_file("fileNine", "nine.tpl");

// 设置行块(bloRow)
$objTmplt->set_block("fileNine", "bloRow", "row");
// 解析行块,使生成9个列块(bloCol1、bloCol2、……、bloCol9)
for ($i = 1; $i <= 9; $i++) {
    $objTmplt->set_var("row_num", $i);
    $objTmplt->parse("row", "bloRow", true);
}

// 解析列块
for ($i = 1; $i <= 9; $i++) {
    // 注意,生成的9个列块是被解析在row模版变量中,而不是fileNine
    $objTmplt->set_block("row", "bloCol".$i, "col".$i);
    // 循环对当前行的每一列进行解析
    for ($j = 1; $j <= 9; $j++) {
        $objTmplt->set_var("grid_value", $i * $j);
        $objTmplt->parse("col".$i, "bloCol".$i, true);
    }
}

// 文件fileNine中的全部模版变量解析到out并输出结果
$objTmplt->parse("out", "fileNine");
$objTmplt->p("out");
?>

当然这个乘法表太简陋了,但并不妨碍此处说明问题。读者有兴趣可以自己做一个美化加强版。

上面的这种实现方法效率会比较低(当然对于乘法表而言此种效率是足够用了),主要问题出在模版类的set_block方法在第二个for循环中执行了9次,而set_block方法是通过正则表达式匹配寻找块的开头<!-- BEGIN block_name -->和结尾<!-- END block_name -->的,当模版文件比较大时,字符串搜索的时间就已经比较长,更何况要用for循环来进行此种搜索。

优化的方法是把子模版提取出来,单独放到一个模版文件中。不用担心模版文件的I/O读写会增加耗时,因为这个子模版文件只需要读一次。请看程序:

nine.tpl文件:

<html>
<head>
<title>九九乘法表</title>
</head>
<body>
<table>
    <!-- BEGIN bloRow -->
    <tr>
    {cols{row_num}}
    </tr>
    <!-- END bloRow -->
</table>
</body>
</html>

nine_sub.tpl文件:

<td>{grid_value}</td>

nine.php文件:

<?php
// 包含PHPLIB的模版类文件
require_once("template.inc");

// 创建模版实例并打开模版文件
$objTmplt = new Template();
$objTmplt->set_file("fileNine", "nine.tpl");
// 打开子模版
$objTmplt->set_file("fileSub", "nine_sub.tpl");

// 设置行块(bloRow)
$objTmplt->set_block("fileNine", "bloRow", "row");
// 解析行块,使生成9个列模版变量(cols1、cols2、……、cols9)
for ($i = 1; $i <= 9; $i++) {
    $objTmplt->set_var("row_num", $i);
    $objTmplt->parse("row", "bloRow", true);
}

// 解析列块
for ($i = 1; $i <= 9; $i++) {
    // 此处已经不需要再用set_block来设置块了
    // 循环对当前行的每一列进行解析
    for ($j = 1; $j <= 9; $j++) {
        $objTmplt->set_var("grid_value", $i * $j);
        // 注意,解析列语句要改成这样,把子模版文件解析到上面生成的9个列模版变量中
        $objTmplt->parse("cols".$i, "fileSub", true);
    }
}

// 文件fileNine中的全部模版变量解析到out并输出结果
$objTmplt->parse("out", "fileNine");
$objTmplt->p("out");
?>

当模版文件比较大,模版内容处理比较复杂时,此种优化可以获得相当可观的效率提升。

Share/Save/Bookmark
最后修改:Wen 于 2005-08-20 10:39:50

发表于 2005-05-01 17:16:22

评论:将优化进行到底

好(0) 差(0) #1
Wen 给 Wen 发消息 给 Wen 发email
poster face
等级:◆◆◆◆◇◇

当列数据在程序中是按行的顺序而得到时(此句不好理解,下文会逐渐解释),可以减少一个for循环,进行更彻底的优化。先回顾原来的优化代码,是通过解析完行块,得到每行的列模版变量cols{row_num}(这里{row_num}被解析后变成具体的行号),然后向这些列模版变量cols{row_num}填充数据。这里的进一步优化就是解析行块之前就把列数据准备好,解析行块的同时就把列数据解析了,不需要等所有行块解析好再从第一个行块解析列数据。

代码如下(nine_sub.tpl文件不需要修改):

nine.tpl文件:

<html>
<head>
<title>九九乘法表</title>
</head>
<body>
<table>
    <!-- BEGIN bloRow -->
    <tr>
    {bloRow.cols}
    </tr>
    <!-- END bloRow -->
</table>
</body>
</html>

nine.php文件:

<?php
// 包含PHPLIB的模版类文件
require_once("template.inc");

// 创建模版实例并打开模版文件
$objTmplt = new Template();
$objTmplt->set_file("fileNine", "nine.tpl");
// 打开子模版
$objTmplt->set_file("fileSub", "nine_sub.tpl");

// 设置行块(bloRow)
$objTmplt->set_block("fileNine", "bloRow", "row");
// 此处不需要解析行块,待每行的列解析完再解析
for ($i = 1; $i <= 9; $i++) {
    // 循环对当前行的每一列进行解析
    for ($j = 1; $j <= 9; $j++) {
        $objTmplt->set_var("grid_value", $i * $j);
        // 注意,解析列语句要改成这样,把子模版文件解析到列模版变量中
        $objTmplt->parse("bloRow.cols", "fileSub", true);
    }
    // 这里才解析行块,这时列模版变量已经填好数据了
    $objTmplt->parse("row", "bloRow", true);
    // 清除列数据
    $objTmplt->set_var("bloRow.cols");
}

// 文件fileNine中的全部模版变量解析到out并输出结果
$objTmplt->parse("out", "fileNine");
$objTmplt->p("out");
?>

注:此种方法只适用于在解析行块前能准备好相应列数据的情况(对于九九乘法表,在解析第3行前可以方便计算出所有第1行的列数据:3*1=3、3*2=6、……),如果列数据需要向行随机填充则只能用原来的优化方法。

例如在一个bbs显示各版最新帖子的页面中,可能需要从数据库按时间倒序取出全站最新帖子(相当于列数据),然后把这些帖子填充到相应的论坛版块(相当于行块),由于最新帖子的论坛版块并不是按顺序的,所以此种方法就不适用。

当然如果每次是从各版取出最新帖子而不是全站,则可以使用此法,但显然sql查询次数增多了(前者只需一次sql查询可获得各版新贴,后者每个版都要sql查询一次)

最后修改:Wen 于 2005-08-20 10:41:37

发表于 2005-05-04 12:30:59

评论:Re: 优化php嵌套模版

好(0) 差(0) #2
Wen 给 Wen 发消息 给 Wen 发email
poster face
等级:◆◆◆◆◇◇

后续相关:优化PHP程序


发表于 2005-09-02 12:50:28
奇技淫巧 - 阅读主题
<<  <  1  >  >>
发表评论
评论将以 过客 的名义发表
你的名字/昵称:
为减少垃圾评论,请准确回答问题:

注意:不超过 65535 字节,不支持HTML,支持NN Code

| | | 注册 | 忘记密码
分类浏览: 足迹 | 美食 | 开心 | 奇技淫巧 | 科学 | 音视 | 琐事 | WENSH事务 | 过客留言 | 前梦想国度 |
English categories: Footprints | Recipes | Fun | Tech | Science | Entertainment | Life | WENSH Affairs | Guests' Msgs |
| 链接 | 服务 | 留言 | 关于 NetNest |
Valid XHTML 1.0 | Valid CSS2 | WAI-A WCAG 1.0
LinkReferral | Multiply the traffic to your website... FREE
W3Csites.com Listed | Travel blogs | Travel | Top Blogs | blogarama.com
Directory of Travel Blogs | Travel Blogs - Blog Top Sites | Web Hosting Directory by Blog Flux | | Blog Ratings
Copyright 2005-2008 WEN'S Horizon [34/0.036]
Powered by NetNest 2.1.0.081019 © 2004-2008 NetNest Group