php無限極分類
這裏首先介紹一下,什麼是無限極分類?php
無限極分類簡單點說就是一個類能夠分紅多個子類,而後一個子類又能夠分另外多個子類這樣無限分下去,就好象windows能夠新建一個文件夾,而後在這個文件夾裏又能夠建一些個文件夾,在文件夾底下還能夠建一些文件夾同樣linux
那PHP又是如何實現它的無限分類的呢?如何把它的各個分類一一列出來呢?sql
首先,咱們來假設有這樣一個數組數據庫
$arr = array( 0=>array( 'cid'=>1, 'pid'=>0, 'name'=>'亞洲', ), 1=>array( 'cid'=>2, 'pid'=>0, 'name'=>'北美洲', ), 2=>array( 'cid'=>3, 'pid'=>1, 'name'=>'中國', ), 3=>array( 'cid'=>4, 'pid'=>2, 'name'=>'美國', ), 4=>array( 'cid'=>5, 'pid'=>3, 'name'=>'北京', ), 5=>array( 'cid'=>6, 'pid'=>3, 'name'=>'河北', ), 6=>array( 'cid'=>7, 'pid'=>5, 'name'=>'東城區', ), 7=>array( 'cid'=>8, 'pid'=>5, 'name'=>'海淀區', ), );
咱們這裏須要一個相似這樣的展現效果如圖
編程
若是咱們要想將這個數組如上圖般很直觀的表現出來的話就須要用php的遞歸來實現,那麼怎麼實現呢?看下面的核心代碼小程序
複製代碼windows
private function GetTree($arr,$pid,$step){ global $tree; foreach($arr as $key=>$val) { if($val['pid'] == $pid) { $flg = str_repeat('└―',$step); $val['name'] = $flg.$val['name']; $tree[] = $val; $this->GetTree($arr , $val['cid'] ,$step+1); } } return $tree; }
複製代碼
而後咱們只須要寫一個調用的代碼就好數組
$newarr = $this->GetTree($arr, 0, 0);
根據子類id查找出全部父級分類信息(yii2框架中)緩存
方法一:服務器
public static function get_parent_list($arr,$id){ //$arr 全部分類列表 //$id 父級分類id static $list=array(); foreach($arr as $u){ if($u['id']== $id){//父級分類id等於所查找的id $list[]=$u; if($u['parent_id']>0){ self::get_parent_list($arr,$u['parent_id']); } } } return $list; }
這樣能夠把分類信息儲存到緩存裏,而不須要遞歸查詢。
方法二:遞歸查詢取分類信息
public static function get_parents($id){ static $list = []; $cat_data = Category::findOne($id)->toarray(); if($cat_data){ $list[] = $cat_data; $id = $cat_data['parent_id']; if($cat_data['parent_id'] > 0){ self::get_parents($id); } } return $list; }
因爲須要實現無限級分類,因此咱們須要知道它的子欄目有什麼?
最後實現的數組是這樣的形式:
[php] view plain copy Array ( [0] => Array ( [category_id] => 1 [category_name] => 關於我 [category_pid] => 0 [category_addtime] => 0 [category_order] => 0 ) [1] => Array ( [category_id] => 2 [category_name] => 生活隨筆 [category_pid] => 0 [category_addtime] => 0 [category_order] => 0 ) [2] => Array ( [category_id] => 3 [category_name] => 文章類別 [category_pid] => 0 [category_addtime] => 0 [category_order] => 0 [category_child] => Array ( [0] => Array ( [category_id] => 4 [category_name] => Linux服務器 [category_pid] => 3 [category_addtime] => -28800 [category_order] => 1 [category_child] => Array ( [0] => Array ( [category_id] => 5 [category_name] => linux優化 [category_pid] => 4 [category_addtime] => 0 [category_order] => 0 ) [1] => Array ( [category_id] => 6 [category_name] => 虛擬化 [category_pid] => 4 [category_addtime] => 1478228220 [category_order] => 0 ) [2] => Array ( [category_id] => 7 [category_name] => Mysql優化與開發 [category_pid] => 4 [category_addtime] => 1478188800 [category_order] => 0 ) [3] => Array ( [category_id] => 8 [category_name] => 高可用與虛擬化 [category_pid] => 4 [category_addtime] => 1478394120 [category_order] => 0 ) ) ) [1] => Array ( [category_id] => 15 [category_name] => Mysql [category_pid] => 3 [category_addtime] => 1480555980 [category_order] => 0 [category_child] => Array ( [0] => Array ( [category_id] => 16 [category_name] => 優化 [category_pid] => 15 [category_addtime] => 1480555980 [category_order] => 0 ) [1] => Array ( [category_id] => 17 [category_name] => Sql編程 [category_pid] => 15 [category_addtime] => 1480556040 [category_order] => 8 ) ) ) ) ) )
那麼咱們從數據庫中取出來的二維數組如何才能變成上面這樣的數組呢?
舉例:
咱們要把下面這個二維數組實現成上面那種形式。
[php] view plain copy
$arr=array( array('id'=>'1','name'=>'北京','pid'=>'0'), array('id'=>'2','name'=>'上海','pid'=>'0'), array('id'=>'3','name'=>'浦東','pid'=>'2'), array('id'=>'4','name'=>'朝陽','pid'=>'1'), array('id'=>'5','name'=>'廣州','pid'=>'0'), array('id'=>'6','name'=>'三里屯','pid'=>'4'), array('id'=>'7','name'=>'廣東','pid'=>'5'), array('id'=>'8','name'=>'三裏','pid'=>'4'), array('id'=>'10','name'=>'小衚衕','pid'=>'8') );
第一種方法:利用數組的索引與主鍵的id號相同來查找子欄目,首先爲數組加上索引:
[php] view plain copy
$arr=array( 1=>array('id'=>'1','name'=>'北京','pid'=>'0'), 2=>array('id'=>'2','name'=>'上海','pid'=>'0'), 3=>array('id'=>'3','name'=>'浦東','pid'=>'2'), 4=>array('id'=>'4','name'=>'朝陽','pid'=>'1'), 5=>array('id'=>'5','name'=>'廣州','pid'=>'0'), 6=>array('id'=>'6','name'=>'三里屯','pid'=>'4'), 7=>array('id'=>'7','name'=>'廣東','pid'=>'5'), 8=>array('id'=>'8','name'=>'三裏','pid'=>'4'), 10=>array('id'=>'10','name'=>'小衚衕','pid'=>'8') );
利用索引的下標,判斷該欄目是否存在父欄目,若是存在就把該欄目放到父欄目的son子數組裏面
[php] view plain copy
function generateTree($items){ $tree = array(); foreach($items as $item){ //判斷是否有數組的索引== if(isset($items[$item['pid']])){ //查找數組裏面是否有該分類 如 isset($items[0]) isset($items[1]) $items[$item['pid']]['son'][] = &$items[$item['id']]; //上面的內容變化,$tree裏面的值就變化 }else{ $tree[] = &$items[$item['id']]; //把他的地址給了$tree } } return $tree; }
上面這個程序有一個主要問題,數組的索引是咱們手動添加的?那咱們可不能夠自動添加數組索引呢?固然能夠,下面這個程序就實現了,自動爲數組添加索引而後再把子欄目放到父欄目的son數組中,思想和上面的程序是同樣的
[php] view plain copy
function make_tree($list,$pk='id',$pid='pid',$child='_child',$root=0){ $tree=array(); $packData=array(); foreach ($list as $data) { <span style="white-space:pre"> </span>//轉換爲帶有主鍵id的數組 $packData[$data[$pk]] = $data; //$packData[1]=$data; $packData[2]=$data } foreach ($packData as $key =>$val){ if($val[$pid]==$root){ //表明跟節點 $tree[]=& $packData[$key]; }else{ //找到其父類 $packData[$val[$pid]][$child][]=& $packData[$key]; } } return $tree; }
第二種方法:使用遞歸來查找子欄目
思想:使用遞歸來查找每一個欄目中的子欄目,直到找到最後一個子欄目之後再一層層往外運行調試的話,能夠打印tree看一下,會發現,第一個打印的不是最後一個子欄目,而是三里屯,而後是北京的最後一個子欄目小衚衕,這個是由於遞歸的時候,三里屯和三裏在一個層級,三里屯下面沒有子欄目直接跳出循環輸出了,因此三里屯會在第一個tree看一下,會發現,第一個打印的不是最後一個子欄目,而是三里屯,而後是北京的最後一個子欄目小衚衕,這個是由於遞歸的時候,三里屯和三裏在一個層級,三里屯下面沒有子欄目直接跳出循環輸出了,因此三里屯會在第一個tree中,,爲了方便理解,能夠打印$tree去觀察數組的變化
[php] view plain copy
array('id'=>'6','name'=>'三里屯','pid'=>'4'), [php] view plain copy function make_tree1($list,$pk='id',$pid='pid',$child='_child',$root=0){ $tree=array(); foreach($list as $key=> $val){ if($val[$pid]==$root){ //獲取當前$pid全部子類 unset($list[$key]); if(! empty($list)){ $child=make_tree1($list,$pk,$pid,$child,$val[$pk]); //來來來 找北京的子欄目 遞歸 空 if(!empty($child)){ $val['_child']=$child; } } $tree[]=$val; } } return $tree; }
爲了更好的理解遞歸,你們能夠找一個小程序測試一下例以下面這個求和的程序
你們能夠分析一下$n的輸出從2,3 …..10,而不是從10,9—-2,我從這個程序才理解了一下上面那個程序的遞歸是如何實現的,總之:遞歸是頗有意思的一個東西,但願你們好好理解
[php] view plain copy
function sum($n){ $a=0; if($n>1){ $a=sum($n-1)+$n; /*if($n>5){ echo "$n <br />" ; }*/ echo "$n<br />"; }else{ $a=1; } return $a; } echo sum(10);
根據父id得到全部下級子類id的數據
#$id = 父級id, $array = 全部分類 public function getSon($id,$array){ static $list; foreach ($array as $k => $v) { if($v['parent_id'] == $id){ $list[] = $array[$k]; self::getSon($v['id'],$array); } } return $list; }