上來補充一下.
不知道各位有使用那一種樣板系統呢? 我們目前是使用 phplib 中的 template.inc 這個模組. (因為一開始就用了, 如果現在要換, 可能有點麻煩)
樣板好用嗎? 沒錯, 樣板的確很好用.
但是我們發現, 如果使用 template.inc 中的 block 功能時, 如果行數過多, 處理的速度會慢的嚇人.
<!-- BEGIN vs_row -->
<tr>
<!-- BEGIN vs_data -->
<td width="{VS_SIZE}%" align="{VS_ALIGN}"{VS_BGCOLOR}><font face="Arial" size="2"> {VS_DATA} </font></td>
<!-- END vs_data -->
</tr>
<!-- END vs_row -->
舉例來說, 一般我們如果要產生一個 table, 就表示這個 table 的每一行都是類似的情形, 所以很簡單的就使用像上述這樣的處理方式.
先使用一個 row block 來表示每一行的資料, 再使用一個 data block 來處理每一個欄位的資料.
所以在程式上可能會是這樣.
$row_name = "vs_row";
$row_var = "vs_rows";
$t->set_block("fHandle", $row_name, $row_var);
$data_name = "vs_data";
$data_var = "vs_datas";
$data_item = "VS_DATA";
$t->set_block($row_name, $data_name, $data_var);
for ($i = 0; $i < $item; $i++) {
if (($i % 2) == 0)
$bgcolor = '';
else
$bgcolor = ' bgcolor="white"';
// time
$t->set_var('VS_SIZE', '12');
$t->set_var('VS_ALIGN', 'center');
$t->set_var('VS_BGCOLOR', $bgcolor);
$t->set_var($data_item, $data[$i]['time']);
$t->parse($data_var, $data_name, false);
// calls offered
$t->set_var('VS_SIZE', '11');
$t->set_var('VS_ALIGN', 'right');
$t->set_var('VS_BGCOLOR', $bgcolor);
$t->set_var($data_item, number_format($data[$i]['abncalls']+$data[$i]['acdcalls']));
$t->parse($data_var, $data_name, true);
.....
// maxocw
$t->set_var('VS_SIZE', '11');
$t->set_var('VS_ALIGN', 'right');
$t->set_var('VS_BGCOLOR', $bgcolor);
$t->set_var($data_item, get_time_str($data[$i]['maxocw']));
$t->parse($data_var, $data_name, true);
$t->parse($row_var, $row_name, true);
}
使用一個 loop 來產生所有的資料.
這樣子的處理方式, 在一般的處理上來看, 是不會有問題的, 可是, 如果你處理一個很大的 table 時, 你會發現, 產生資料的速度會隨著你的資料的增加而變慢, 而且對於一個 web 的系統來說, 這個慢的速度可能會讓人無法接受.
我們在查了一陣子之後, 才發現原來系統最主要會慢的原因就是這個. :-(
因為我們在處理這個 block 時, 你可以發現都應該只是簡單的字串轉換, 而不會有其它的運算. 所以我們決定自己寫一個小的模組, 來處理這類簡單的樣板.
class MyRowTemplate
{
var $sResult = '';
var $sOldData = '';
var $sTempData = '';
function MyRowTemplate($file)
{
$this->sOldData = file_get_contents($file);
}
function row_begin()
{
$this->sTempData = $this->sOldData;
}
function row_end()
{
$this->sResult .= $this->sTempData;
}
function set_var($var, $value)
{
$this->sTempData = str_replace('{'.$var.'}', $value, $this->sTempData);
}
function get_result()
{
return $this->sResult;
}
}
然後把樣板拆成下面這兩個樣子.
{DETAIL}
<tr{BGCOLOR}>
<td width="12%" align="center"><font face="Arial" size="2"> {TIME} </font></td>
<td width="10%" align="right"><font face="Arial" size="2"> {OFFCALLS} </font></td>
<td width="10%" align="right"><font face="Arial" size="2"> {ANSTIME} </font></td>
<td width="10%" align="right"><font face="Arial" size="2"> {ABNTIME} </font></td>
<td width="10%" align="right"><font face="Arial" size="2"> {ACDCALLS} </font></td>
<td width="10%" align="right"><font face="Arial" size="2"> {ACDTIME} </font></td>
<td width="10%" align="right"><font face="Arial" size="2"> {ABNCALLS} </font></td>
<td width="9%" align="right"><font face="Arial" size="2"> {ABNRATE} </font></td>
<td width="10%" align="right"><font face="Arial" size="2"> {IN_SL} </font></td>
<td width="9%" align="right"><font face="Arial" size="2"> {SL} </font></td>
</tr>
把處理的程式改成:
$oRows = new MyRowTemplate('xxx.tpl');
for ($i = 0; $i < $item; $i++) {
if (($i % 2) == 0)
$bgcolor = '';
else
$bgcolor = ' bgcolor="white"';
$oRows->row_begin();
$oRows->set_var('BGCOLOR', $bgcolor);
// time
$oRows->set_var('TIME', $data[$i]['time']);
....
// service level
if ($data[$i]['acdcalls'] == 0)
$oRows->set_var('SL', '100.00%');
else
$oRows->set_var('SL', sprintf("%.2f%%", 100 * $data[$i]['in_sl']/$data[$i]['acdcalls']));
$oRows->row_end();
}
$t->set_var('DETAIL', $oRows->get_result());
經過類似的處理, 我們把原本產生約六百行的 table, 時間由 10 秒左右, 大幅降到 0.03 秒左右.
或許在處理上, 並沒有之前的方便, 但是, 速度的改進是十分驚人的.
我不確定其它的樣板系統 (如 FastTemplate, Smarty...), 會不會有類似的問題, 不過, 如果你使用 phplib 的 template.inc, 在你有需要產生大的 table 時, 或許可以考慮我們的處理方式.