#在日常的專案中,我們常常會接觸到無限極分類。一般情況下無限極分類有兩種實現的方式。第一種方式是通過資料表中的父ID。從而去一層一層地往上找。第二種方式是通過記錄分類的全路徑進行實現。接下來我將會根據兩種不同的方法,通過編寫小案例讓您可以更快的理解和熟悉無限極分類。
#本次的程式碼案例實現是基於laravelDB運算元據庫。因此這裡呼叫的是直接的資料模型去獲取資料。但是其實現的原理適用於各個框架與平臺。
1.基於通過父級ID獲取對應的無限極分類方法。
1.首先我們展示一下資料庫的說明與建立
CREATE TABLE `deepcate` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pid` int(11) DEFAULT NULL,
`catename` varchar(11) DEFAULT NULL,
`cateorder` int(11) DEFAULT NULL COMMENT '排序欄位',
`createtime` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
#分類表中 我們需要注意,我們要為對應的分類建立一個pid欄位用於儲存資料的上級ID複製程式碼
2.為我們的資料表新增適當的測試資料
INSERT INTO `deepcate` VALUES (1,0,'新聞',0,0),(2,0,'圖片',0,0),(3,1,'國內新聞',0,0),(4,1,'國外新聞',0,0),(5,2,'風景圖片',0,0),(6,2,'美女圖片',0,0),(7,4,'美國新聞',0,0),(8,3,'廣東新聞',0,0),(9,5,'海灘風景',0,0),(10,6,'模特風采',0,0);
複製程式碼
案例:1
編寫獲通過父ID方式取無限極分類列表的方法
程式設計思路:
1.獲取所有的分類資訊,並指定預設的頂級分類ID
2.遍歷迴圈傳入的資料,並判斷當前的資料是否屬於傳入的頂級ID
3.如果判斷為真則利用遞迴特性判斷當前的資料中是否存在下級
4.如果完成判斷,則返回輸出的資料
//首先我們獲取分類資訊表中的所有資料並儲存到變數$data中
$data=DB::table('deepcate')->get()->toarray();
//編寫獲取分類樹的方法
/**
* 作者:逍遙俠
* 建立時間:2018/10/29
* @param int $pid 父級ID
* @param $data 傳入的資料
* @param $level 當前的等級結構
* @return array 返回資料
*/
public function get_tree($pid=0,$data,$level){
//定義靜態的陣列存放變數
static $arr=[];
//遍歷資料
foreach ($data as $k=>$v){
//判斷當前遍歷的資料的父級是否為傳入的pid
if($v->pid==$pid){;
$arr[$k]['name']=$v->catename;
$arr[$k]['id']=$v->id;
$arr[$k]['level']=$level;
//判斷當前資料中是否存在子分類,並給對應的結果+1
$this->get_tree($v->id,$data,$level+1);
}
}
return $arr;
}
#執行的結果
array:10 [▼
0 => array:3 [▼
"name" => "新聞"
"id" => 1
"level" => 0
]
2 => array:3 [▼
"name" => "國內新聞"
"id" => 3
"level" => 1
]
7 => array:3 [▼
"name" => "廣東新聞"
"id" => 8
"level" => 2
]
3 => array:3 [▼
"name" => "國外新聞"
"id" => 4
"level" => 1
]
6 => array:3 [▼
"name" => "美國新聞"
"id" => 7
"level" => 2
]
1 => array:3 [▼
"name" => "圖片"
"id" => 2
"level" => 0
]
4 => array:3 [▼
"name" => "風景圖片"
"id" => 5
"level" => 1
]
8 => array:3 [▼
"name" => "海灘風景"
"id" => 9
"level" => 2
]
5 => array:3 [▼
"name" => "美女圖片"
"id" => 6
"level" => 1
]
9 => array:3 [▼
"name" => "模特風采"
"id" => 10
"level" => 2
]
]複製程式碼
案例:2
編寫通過父ID方式獲取麵包屑導航
程式設計思路:
1.通過傳入的ID獲取對應的資料
2.判斷資料是否為真,如果為真則儲存對應需要的變數值,利用遞迴特性,傳入該資料中的父級ID繼續獲取資料
//獲取麵包屑導航
$bread=$this->get_bread(10);
/**
* 作者:逍遙俠
* 建立時間:2018/10/29
* @param $id 傳入的對應ID
* @return array
*/
public function get_bread($id){
//定義靜態的陣列存放變數
static $arr=[];
//根據傳入的ID獲取對應的分類資訊
$res=DB::table('deepcate')->find($id);
//判斷能否獲取資料
if($res){
$data['name']=$res->catename;
$data['id']=$res->id;
array_push($arr,$data);
//傳入該資料的父級ID作為查詢元素判斷是否存在
$this->get_bread($res->pid);
}
//重新排序
krsort($arr);
return $arr;
}
#執行結果
array:3 [▼
2 => array:2 [▼
"name" => "圖片"
"id" => 2
]
1 => array:2 [▼
"name" => "美女圖片"
"id" => 6
]
0 => array:2 [▼
"name" => "模特風采"
"id" => 10
]
]
複製程式碼
2.基於全路徑模式獲取對應的無限極分類方法
1.首先我們展示一下資料庫的說明與建立
CREATE TABLE `fullpath` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`path` varchar(255) DEFAULT NULL COMMENT '全路徑',
`catename` varchar(255) DEFAULT NULL COMMENT '分類名稱',
`cateorder` int(11) DEFAULT NULL COMMENT '排序',
`createtime` int(11) DEFAULT NULL COMMENT '建立時間',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
複製程式碼
2.為我們的資料表新增適當的測試資料
INSERT INTO `fullpath` VALUES (1,'','手機',0,0),(2,'1','功能手機',0,0),(3,'1.2','老人手機',0,0),(4,'1.2','兒童手機',0,0),(5,'1','智慧手機',0,0),(6,'1.5','IOS手機',0,0),(7,'1.5','WinPhoto手機',0,0),(8,'1.5','android手機',0,0),(9,'1.2.4','色盲手機',0,0),(10,'1.2.3','大字手機',0,0);
複製程式碼
案例:1
編寫獲通過全路徑方式取無限極分類列表的方法
程式設計思路:
1.獲取所有的分類資料,並按全路徑欄位排序
2.遍歷資料,根據全路徑的層級深度設定對應的級別層次
$full_tree=$this->get_full_tree();
/**
* 作者:逍遙俠
* 建立時間:2018/10/29
* @return mixed 返回資料
*/
public function get_full_tree(){
//獲取所有的分類資料,並通過full欄位排序
$data=DB::table('fullpath')->select(DB::raw('id,catename,path,concat(path,\'.\',id) as full'))->orderBy('full','asc')->get();
//遍歷所有資料
foreach ($data as $k=>$v){
//根據過濾後的全路徑欄位獲取對應的分類層級等級
$data[$k]->level=count(explode('.',trim($v->full,'.')));
}
return $data;
}
#注意由於我們資料表的欄位是沒有full這個欄位的,所以我們使用mysql裡的concat函式,利用對應的資料的path欄位與id欄位結合一個新的欄位。該sql的原生寫法為:
select id,path,catename,concat(path,'.',id) as full from `fullpath` order by full asc
#執行結果
Collection {#616 ▼
#items: array:10 [▼
0 => {#605 ▼
+"id": 1
+"catename": "手機"
+"path": ""
+"full": ".1"
+"level": 1
}
1 => {#606 ▼
+"id": 2
+"catename": "功能手機"
+"path": "1"
+"full": "1.2"
+"level": 2
}
2 => {#607 ▼
+"id": 3
+"catename": "老人手機"
+"path": "1.2"
+"full": "1.2.3"
+"level": 3
}
3 => {#608 ▼
+"id": 10
+"catename": "大字手機"
+"path": "1.2.3"
+"full": "1.2.3.10"
+"level": 4
}
4 => {#609 ▼
+"id": 4
+"catename": "兒童手機"
+"path": "1.2"
+"full": "1.2.4"
+"level": 3
}
5 => {#610 ▼
+"id": 9
+"catename": "色盲手機"
+"path": "1.2.4"
+"full": "1.2.4.9"
+"level": 4
}
6 => {#611 ▼
+"id": 5
+"catename": "智慧手機"
+"path": "1"
+"full": "1.5"
+"level": 2
}
7 => {#612 ▼
+"id": 6
+"catename": "IOS手機"
+"path": "1.5"
+"full": "1.5.6"
+"level": 3
}
8 => {#613 ▼
+"id": 7
+"catename": "WinPhoto手機"
+"path": "1.5"
+"full": "1.5.7"
+"level": 3
}
9 => {#614 ▼
+"id": 8
+"catename": "android手機"
+"path": "1.5"
+"full": "1.5.8"
+"level": 3
}
]
}複製程式碼
案例2:
編寫獲通過全路徑方式取麵包導航的方法
程式設計思路:
1.根據傳入的ID獲取對應ID
2.根據全路徑欄位,把字串分割為陣列
3.根據分割的陣列,利用wherein方法獲取包含的資料
$full_bread=$this->get_full_bread(10);
/**
* 作者:逍遙俠
* 建立時間:2018/10/29
* @param $id 傳入的對應ID
* @return mixed 返回資料
*/
//獲取全路徑麵包屑導航
public function get_full_bread($id){
//根據ID獲取全路徑的麵包屑導航
$data=DB::table('fullpath')->select(DB::raw('id,catename,path,concat(path,\'.\',id) as full'))->orderBy('full','asc')->find($id);
//分割對應的全路徑陣列
$ids=explode('.',trim($data->full,'.'));
//根據分割的ID陣列獲取對應的資料
$bread=DB::table('fullpath')->wherein('id',$ids)->orderby('id','asc')->get();
return $bread;
}
#執行結果
Collection {#667 ▼
#items: array:4 [▼
0 => {#662 ▼
+"id": 1
+"path": ""
+"catename": "手機"
+"cateorder": 0
+"createtime": 0
}
1 => {#663 ▼
+"id": 2
+"path": "1"
+"catename": "功能手機"
+"cateorder": 0
+"createtime": 0
}
2 => {#664 ▼
+"id": 3
+"path": "1.2"
+"catename": "老人手機"
+"cateorder": 0
+"createtime": 0
}
3 => {#665 ▼
+"id": 10
+"path": "1.2.3"
+"catename": "大字手機"
+"cateorder": 0
+"createtime": 0
}
]
}
複製程式碼