首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

ThinkPHP volist 標籤 mod 屬性換行 Bug 根因與修正方案

     編輯:PHP 相關知識

ThinkPHP volist 標籤 mod 屬性換行 Bug 根因與修正方案

ThinkPHP 2.x 模板引擎的 <volist> 標籤提供 mod 屬性配合 $mod 變數實現「每 N 筆換行」功能。但官方手冊範例在第一行會少輸出一筆資料(如 mod=5,第一行僅 4 筆),導致版面錯亂。本文解析核心原始碼,給出精確修正位置與替代寫法。

一、Bug 重現

<volist name="list" id="vo" mod="5">
    {$vo.name}
    <eq name="mod" value="4"><br/></eq>
</volist>

預期: 每 5 筆換行(索引 0-4,第 4 筆後換行)。
實際: 第一行輸出 4 筆(索引 0-3),第二行起才正常 5 筆。

二、核心原始碼定位與根因

檔案:ThinkPHP/Lib/Think/Template/TagLib/TagLibCx.class.php(約第 107-108 行)

// 原始碼(有 Bug)
$parseStr .= '++$'.$key.';';          // 先遞增索引
$parseStr .= '$mod = ($'.$key.' % '.$mod.' )?>'; // 再計算 mod

邏輯錯誤: 迴圈開始時 $key=0,先 ++$key 變 1,再 1 % 5 = 1,導致第一筆 $mod=1,而非預期的 0。第 5 筆時 $key=5,5%5=0,判斷 value="4" 失效,故第一行少一筆。

三、官方修正(交換兩行順序)

// 修正後
$parseStr .= '$mod = ($'.$key.' % '.$mod.' );'; // 先計算 mod(基於當前索引)
$parseStr .= '++$'.$key.'?>';                   // 再遞增索引供下輪

修正後:
第 1 筆:$key=0 → $mod=0%5=0 → ++$key=1
第 5 筆:$key=4 → $mod=4%5=4 → 滿足 value="4" 換行 → ++$key=5
完全符合預期。

四、不修改核心的替代寫法(推薦,升級安全)

利用 key 屬性自訂索引變數,配合 neq 避免最後多餘換行:

<volist name="list" id="vo" key="k" mod="5">
    {$vo.title}<br/>
    <eq name="mod" value="4">
        <neq name="k" value="$count"><br /></neq>
    </eq>
</volist>
  • key="k":索引從 1 開始($k=1,2,3...)
  • mod="5":$mod = ($k % 5) → 1,2,3,4,0 循環
  • value="4":第 4 筆($mod=4)換行
  • neq name="k" value="$count":最後一筆不換行

五、自增序號顯示($i 或自訂 key)

<volist name="list" id="vo">
    {$i} - {$vo.name}  // 預設 $i 從 1 開始
</volist>

<volist name="list" id="vo" key="idx">
    {$idx} - {$vo.name} // 自訂變數 $idx
</volist>

六、ThinkPHP 3.2+ / 5.x / 6.x 狀況

  • 3.2 版已修正此 Bug(原始碼順序正確)。
  • 5.x/6.x 推薦使用 {:foreach} 或 volist 但內部邏輯已重寫,無此問題。
  • 若維護 2.x 老專案,建議套用核心修正或改用替代寫法。

總結: Bug 成因是模板編譯階段「遞增索引」與「計算 mod」順序顛倒。修正核心檔只需交換兩行;若不想動核心,使用 key+mod+neq 組合更靈活且升級無憂。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved