一、從數據庫查出來的數據需要id、parentid、level。
id唯一識別欄目,parentid為該欄目所屬父類id,level標示該欄目是幾級欄目。以下代碼就可以實現一個簡單的樹結構。
1 public function tree2(){ 2 $r = array( 3 array( 4 'id'=>1, 5 'name'=>'智慧教育', 6 'parent_id'=>0, 7 'level'=>0 //一級分類 8 ), 9 array( 10 'id'=>2, 11 'name'=>'學校列表', 12 'parent_id'=>1, 13 'level'=>1 //二級分類 14 ), 15 array( 16 'id'=>4, 17 'name'=>'智慧醫療', 18 'parent_id'=>0, 19 'level'=>0 //一級分類 20 ), 21 array( 22 'id'=>5, 23 'name'=>'醫院列表', 24 'parent_id'=>4, 25 'level'=>1 //二級分類 26 ), 27 array( 28 'id'=>6, 29 'name'=>'名醫列表', 30 'parent_id'=>5, 31 'level'=>2 //三級分類 32 ) 33 34 ); 35 //輸出為select標簽: 36 echo '<h1>PHPTree</h1>'; 37 echo '<select style="width:300px;">'; 38 foreach($r as $item){ 39 echo '<option>'; 40 //根據所在的層次縮進 41 echo str_repeat('|—',$item['level']); 42 echo $item['name']; 43 echo '</option>'; 44 } 45 echo '</select>'; 46 }
頁面效果圖是這樣的。
二、但是一般表結構中是沒有level的。
這樣就需要多層循環嵌套加if判斷,先循環顯示父級欄目parentid=0,及它就是一級欄目;然后再循環根據parentid與一級欄目的id判斷,如果相等則顯示對應的欄目,二級欄目就顯示出來啦,以此類推,可以顯示所有欄目。但這只適合已知欄目層數且層數不多的情況,因為要根據層數來判斷遍歷的次數。且如果層數過多,代碼量就會很大。
1 public function tree3(){ 2 //從表中查到所有欄目 3 $cat = M('category'); 4 $allcat = $cat ->order('listorder ASC') ->select(); 5 6 //輸出select標簽 7 echo '<h2>欄目tree</h2>'; 8 echo '<select style="width:300px;">'; 9 foreach ($allcat as $val) { 10 if($val[parentid] == 0){ 11 echo '<option>'; 12 echo $val['catname']; 13 echo '</option>'; 14 } 15 foreach ($allcat as $value) { 16 if($val[id] == $value[parentid]){ 17 echo '<option>'; 18 echo '|—'.$value['catname']; 19 echo '</option>'; 20 } 21 } 22 } 23 ...... 24 }
那怎么知道欄目層數,或者怎么判斷該欄目下面還有沒有子欄目呢?
三、這里采用遞歸的方式
這樣就可以不斷重復查詢本身的pid等於上一級id的數據,通過判斷查到的數據是否為空來判斷它有沒有子欄目。
還有一個問題就是根據級別設置縮進,這樣看着有層次感。那這個怎么實現呢?在php中有一個字符串函數str_repeat(),兩個參數,第一個表示要重復的字符串,第二個是重復的次數。
代碼片段如下:
//遞歸實現無限級菜單 public function tree2($pid=0,$level=0){ $cat = M('category'); $data = $cat ->where("parentid = $pid") ->field('id,catname,parentid') ->select(); $level ++; if(!empty($data)){ $tree = array(); foreach ($data as $val) { $val['catname'] = str_repeat('|—', $level-1).$val['catname']; $child = $this ->tree2($val[id],$level); $tree[] = array('self'=>$val,'child'=>$child,'level'=>$level); } } return $tree; } function test(){ $allcat = $this ->tree2(0); dump(json_encode($allcat)); }
上面tree2方法找到了所有欄目,並組裝到tree數組中,tree是一個多維數組,現在要從數組中取出所有欄目名稱catname,同樣遞歸調用,代碼如下:
//遍歷找出所有catname function getcatname($array){ if(is_array($array)){ foreach ($array as $key=>$value ){ if(is_array($value)){ $this ->getcatname($value); }else{ $temp = array('key'=>$key,'value'=>$value); if ($temp['key'] == 'catname') { echo $temp['value']."<br/>"; } } } } } function test(){ $allcat = $this ->tree2(0); $this ->getcatname($allcat); }
頁面顯示效果圖如下:
這樣就實現了多級欄目的顯示。
