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

ThinkPHP list_to_tree 實現無限級分類遞歸輸出所有節點

     編輯:PHP 相關知識

ThinkPHP list_to_tree 實現無限級分類遞歸輸出所有節點

ThinkPHP 內建 list_to_tree() 函數可將扁平數據轉為樹狀結構,但預設只輸出頂層節點 (含 _child 遞歸)。若需一次性列出所有節點 (如下拉選單、權限樹),需額外遞歸遍歷。

核心代碼

<?php
public function index() {
    Load('extend');  // 載入 extend.php (含 list_to_tree)
    $Category = D('Category');
    
    // 1. 獲取扁平數據,按排序字段排序 (重要:同級順序)
    $list = $Category->order('sort DESC')->select();
    
    // 2. 轉為樹狀結構
    // list_to_tree($list, '主鍵', '父鍵', '子節點鍵名', '根節點pid值')
    $tree = list_to_tree($list, 'id', 'fid', '_child', 0);
    
    // 3. 遞歸展平所有節點
    $flat = $this->flattenTree($tree);
    
    dump($flat);  // 或輸出 JSON 給前端
}

protected function flattenTree($tree) {
    static $result = array();
    foreach ($tree as $node) {
        $result[] = $node;  // 當前節點
        if (isset($node['_child']) && is_array($node['_child'])) {
            $this->flattenTree($node['_child']);  // 遞歸子節點
        }
    }
    return $result;
}
?>

list_to_tree 完整源碼 (ThinkPHP Extend/extend.php)

<?php
/**
 * 扁平數組轉樹狀結構
 * @param array  $list  數據集
 * @param string $pk    主鍵名 (默認 id)
 * @param string $pid   父鍵名 (默認 pid)
 * @param string $child 子節點鍵名 (默認 _child)
 * @param mixed  $root  根節點 PID 值 (默認 0)
 * @return array
 */
function list_to_tree($list, $pk='id', $pid='pid', $child='_child', $root=0) {
    $tree = array();
    if (is_array($list)) {
        $refer = array();
        foreach ($list as $key => $data) {
            $refer[$data[$pk]] =& $list[$key];  // 關鍵:引用賦值
        }
        foreach ($list as $key => $data) {
            $parentId = $data[$pid];
            if ($root == $parentId) {
                $tree[] =& $list[$key];
            } elseif (isset($refer[$parentId])) {
                $parent =& $refer[$parentId];
                $parent[$child][] =& $list[$key];
            }
        }
    }
    return $tree;
}

/**
 * 數組多字段排序
 * @param array $list
 * @param string $field 排序字段
 * @param string $sortby asc|desc|nat
 * @return array
 */
function list_sort_by($list, $field, $sortby='asc') {
    if (is_array($list)) {
        $refer = array();
        foreach ($list as $i => $data) $refer[$i] = &$data[$field];
        switch ($sortby) {
            case 'asc':  asort($refer); break;
            case 'desc': arsort($refer); break;
            case 'nat':  natcasesort($refer); break;
        }
        $result = array();
        foreach ($refer as $key => $val) $result[] = &$list[$key];
        return $result;
    }
    return false;
}

/**
 * 數組條件搜尋
 * @param array $list
 * @param mixed $condition array('field'=>val) 或 'field=val'
 * @return array
 */
function list_search($list, $condition) {
    if (is_string($condition)) parse_str($condition, $condition);
    $result = array();
    foreach ($list as $key => $data) {
        $match = true;
        foreach ($condition as $field => $value) {
            if (!isset($data[$field])) { $match = false; break; }
            if (0 === strpos($value, '/')) {  // 正則模式 /pattern/
                $match = preg_match($value, $data[$field]);
            } elseif ($data[$field] != $value) {
                $match = false;
            }
        }
        if ($match) $result[] = &$list[$key];
    }
    return $result;
}
?>

關鍵點解析

  1. 引用賦值 (&):$refer[$pk] =& $list[$key] 避免複製大數組,節省內存,修改同步
  2. 排序先行:order('sort DESC') 確保同級節點順序正確,否則樹結構順序混亂
  3. 根節點 PID:通常為 0 或 null,視資料表設計而定
  4. 展平函數:使用 static $result 累積,避免層層返回合併的性能開銷

前端下拉選單渲染範例 (層級縮進)

<select name="category_id">
    <?php foreach ($flat as $node): ?>
        <option value="<?php echo $node['id']; ?>" 
                style="padding-left: <?php echo $node['level'] * 20; ?>px;">
            <?php echo str_repeat('— ', $node['level']) . $node['name']; ?>
        </option>
    <?php endforeach; ?>
</select>

注意:list_to_tree 不自動生成 level 字段,展平時可額外計算或前端根據父子關係動態縮進。

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