首先咱們來看數據表php
從上圖中能夠發現,中國下有貴州,北京兩個子節點,而北京有天安門一個子節點,紐約的子節點是「紐約的子類」。thinkphp
從pid爲0看出,中國和紐約是頂級節點。數據庫
由於貴州的pid是1,而中國的id爲1,因此貴州的父節點是中國,至於type字段,能夠不用管,只是我本身的項目須要。數組
能夠發現,着寫數據在數據表中是無序的,並無咱們想象中的層次結構分明而且可讀性很好。app
那麼,當使用無限極分類以後數據的輸出是怎樣的呢?以下:thinkphp5
這樣就可以很清晰的看出他們的層次結構了,那麼這樣的效果在thinkphp5.0是怎麼實現的呢?this
好了,貼出代碼:url
<?php /** * Created by PhpStorm. * User: Administrator * Date: 2017/9/24 * Time: 17:14 */ namespace app\admin\model; use think\Model; class Cate extends Model { public function cateTree(){ $res=$this->select(); if($res){ $result=$this->sort($res); return $result; } } public function sort($data,$pid=0,$level=0){
//此處數據必須是靜態數組,否則遞歸的時候每次都會聲明一個新的數組 static $arr=array(); foreach ($data as $key=>$value){ if($value['pid'] == $pid){ $value["level"]=$level; $arr[]=$value; $this->sort($data,$value['id'],$level+1); } } return $arr; } }
首先咱們能夠看到,在cateTree方法中咱們經過select()方法獲取到了數據庫裏面的全部數據,而後將數據傳入到sort裏面,此刻咱們注意到sort有三個參數,pid表示當前節點的父節點的id,level表示當前節點spa
爲幾級。(頂級節點是0級,頂級節點的子節點是1級),那麼level的用處到時候輸出的時候會用到,此處不用糾結。3d
當數據傳入sort方法以後,聲明一個靜態數組,保證每次遞歸調用的時候數組裏面的數據不會改變,而後循環從數據庫裏面查詢的數據。
$value的值表示數據庫裏面的一行,是一個數組,$value['名字']表示一行裏面的一個字段。
首先咱們經過
$value['pid'] == $pid
判斷當前的pid是否爲0,由於咱們在sort方法一開始的時候就給了一個默認值0,此時$pid爲0。
這樣作的目的就是選出第一個頂級節點。
若是找到了第一個頂級節點,假如是中國,那麼知足if的條件,就進入條件體,先給$value數組加一個level值,而後再把$value整個假如到靜態數組當中去。
而後開始遞歸,注意,此刻sort方法的pid參數接受的是當前節點的id。爲何要這樣傳呢?
舉個例子:
若是咱們循環到了中國,以下圖
第一次遞歸的時候,會將static 數組入棧,以及將變量入棧,並保存程序的斷點,以便遞歸完成以後可以順利的找到進入遞歸出並繼續執行程序。
如上圖,找到中國後,遞歸,入棧,此刻靜態數組裏面只有「中國」一個數據。(注意:數組是一個二維數組,我只是爲了簡便才畫了一維數組,數組裏面還包含了level的信息)。經過pid判斷中國下方是否有子節點,而後匹配到貴州以後,進入遞歸,數據入棧。此時靜態數組裏面又增長了貴州這個數據。
到了貴州以後,發如今咱們的數據表裏面並無貴州的子節點,此時遞歸結束,程序返回遞納入口處,繼續執行循環體,棧空間以下:
當遞歸回來時,貴州出棧,此時棧空間裏面保存的是中國的數據,包括pid爲0這個變量,level爲0這個變量,以及靜態數組。當執行下一個循環時,$value['pid'] == $pid
由於棧空間裏面保存的pid是0,因此會找到北京這個數據。
接下來的步驟就差很少了,首先foreach循環天安門的子節點,發現沒有子節點,遞歸結束,同時將sort($data,7,3)出棧,回到遞歸進入出,以上爲例,則回到天安門那段代碼的sort處,同時執行foreach循環,查找是否有其餘的節點的pid爲6,即查看北京下是否還有其餘子節點。若是有,則將該節點的數據入棧,若是沒有則出棧,回到北京那塊代碼的sort處,匹配pid爲1的是否還有其餘節點。若是沒有則回到最開始的sort處,此時遞歸徹底結束。
此刻咱們來觀察數組,能夠看出,經過遞歸,數組裏的數據開始變得有序起來,如貴州是中國的一級子節點,因此緊跟在中國以後,當第一輪遞歸結束,到了第二輪遞歸時,第一個找到的是北京,因此數組裏面第三個元素是北京。
那怎麼獲得以下的格式化數據呢?
咱們能夠發現,北京和貴州的level是相同的,注意:咱們的數組還保存得有level信息(圖中的level有些錯誤,不建議你們參考)。
level數值大的前面的短線就越多,表示級數就越大。
那麼這是怎麼輸出的呢?
{volist name="cateList" id="cate"} <!--設置URL值,方便JS刪除的時候獲取路徑--> <tr id="{:url('delete',array('id'=>$cate.id))}" class="url"> <td align="center">{$cate.id}</td> <td><?php echo str_repeat("-",$cate["level"]*8)?>{$cate.cate_name}</td> {/volist}
以上是thinkphp的模板標籤,volist和foreach是同樣的道理
經過後臺分配而來的cateList數據(也就是上面的靜態數組),經過
<td><?php echo str_repeat("-",$cate["level"]*8)?>{$cate.cate_name}</td>獲得最終的結果。