本期概要:
使用遞迴實現無限級選單分類
複製程式碼
一、資料結構 一般情況下,我們的資料表常規設計如下:
id | name | pid |
1 | PHP 技術 | 0 |
2 | Linux 技術 | 0 |
3 | PHP 基礎 | 1 |
4 | PHP 高階 | 1 |
5 | PHP 資料型別 | 3 |
6 | PHP 資料型別 - 字串 | 5 |
7 | Linux 基礎 | 2 |
8 | Linux 簡單命令 | 7 |
當我們從資料庫中查詢出資料,得到二維陣列結構如下:
[
[
"id": 1,
"name": "PHP 技術",
"pid": 0
],
[
"id": 3,
"name": "PHP 基礎",
"pid": 1
],
[
"id": 5,
"name": "PHP 資料型別",
"pid": 3
],
[
"id": 6,
"name": "PHP 資料型別 - 字串",
"pid": 5
],
[
"id": 4,
"name": "PHP 高階",
"pid": 1
],
[
"id": 2,
"name": "Linux 技術",
"pid": 0
],
[
"id": 7,
"name": "Linux 基礎",
"pid": 2
],
[
"id": 8,
"name": "Linux 簡單命令",
"pid": 7
]
]
複製程式碼
我們要實現無限級選單,主要核心思路就是:
找出每個選單所在的層級(level)
那麼我們就需要用到遞迴,得出每個選單對應的層級
function _infinite($_data, $_pid = 0, $_level = 0) {
// 定義靜態變數,防止每次都初始化
static $_new_data = [];
// 迴圈,得出每個資料對應的層級
foreach ($_data as $_key => $_value) {
// 第一次遍歷,找到父節點為根節點的節點,即:pid = 0
if ($_value['pid'] == $_pid) {
// 當該節點為根節點時,對應的層級設為 0,即:level = 0
$_value['level'] = $_level;
// 把該節點放入陣列中
$_new_data[] = $_value;
// 得出節點層級後,刪除該節點,減少遞迴的消耗
unset($_data[$_key]);
// 開始遞迴,查詢所有 pid 為當前節點 id 的資料,層級加 1,作為對應的子節點
_infinite($_data, $_value['id'], $_level + 1);
}
}
// 返回帶層級的新陣列
return $_new_data;
}
複製程式碼
呼叫方法,我們可以得到新陣列:
[
[
"id": 1,
"name": "PHP 技術",
"pid": 0,
"level": 0
],
[
"id": 3,
"name": "PHP 基礎",
"pid": 1,
"level": 1
],
[
"id": 5,
"name": "PHP 資料型別",
"pid": 3,
"level": 2
],
[
"id": 6,
"name": "PHP 資料型別 - 字串",
"pid": 5,
"level": 3
],
[
"id": 4,
"name": "PHP 高階",
"pid": 1,
"level": 1
],
[
"id": 2,
"name": "Linux 技術",
"pid": 0,
"level": 0
],
[
"id": 7,
"name": "Linux 基礎",
"pid": 2,
"level": 1
],
[
"id": 8,
"name": "Linux 簡單命令",
"pid": 7,
"level": 2
]
]
複製程式碼
我們得到新資料以後,需要將資料根據需要的 view 展示出來,我這裡使用樹形結構列印:
function _show_tree($_data) {
$_html = '';
foreach ($_data as $_key => $_value) {
if ($_value['level'] > 0) {
$_prefix = '|' . str_repeat('--', $_value['level']);
} else {
$_prefix = '';
}
$_html .= $_prefix . '<a href="###">' . $_value['name'] . '</a><br />';
}
return $_html;
}
複製程式碼
得到效果圖如下:
這樣我們就完成了使用遞迴實現無限級分類的效果。