記得之前有一次去面試,被問了無限級怎麼做。我想很簡單,就說了最基本的結構:id、name、parentid。
又被問就這樣嗎?顯然不被滿意。後面自然就沒通過面試。
遇上技術型面試官,如果問的技術問題不被滿意,大抵就沒有下文了。遇上那些一副老子技術天下第一,狗眼看人低的面試官,那就自認倒霉吧。
遇上追問你如何規劃人生,比如五年規劃什麼的。筆者現在只堪堪在溫飽線上掙扎,只想提高點技術實力,多拿點工資。如果筆者有大能耐,就完全可以和面試官侃侃而談雄心壯志,也可以完全不甩面試官,甚至可以發出乙個鄙夷的眼光。奈何筆者沒什麼能耐,不得不認真回答面試官,卻又因為回答的空泛無力,還要被面試官指手畫腳一番。結果自然又是沒有下文。
畢竟樹形分類在**系統中,查詢是最頻繁的操作,反而在增刪改操作極少。所以在儲存到資料庫時,為了按樹形排序,增加了增刪改的複雜度,卻可以換來查詢上效能的提公升。
此方案的發明者無疑是充滿智慧型的。
不過我想,我只是剛好在實際工作中沒有用到它而已。
沒用過的技術或方案多了去。下次再遇上這種拿幾個技術問題唧唧歪歪的面試官,哥決定了不甩他。
本方案是在mysql+ci php mvc下設計的,所以命名習慣隨俗。
下面是表的設計結構
字段說明
id分類編號
parent_id
分類的父親節點
name
分類名稱
parent_path
父節點的路徑,用於找到乙個節點的子節點和子子節點或所有子節點。也可以找到乙個節點的所有父節點,比如在刪除節點時同時刪除其下所有子節點
order_path
所有節點按樹形排序,可以乙個sql語句提取樹形排序的分類,而不需要遞迴
level
第幾級節點,可以和css配合,美化和層次化顯示效果
order_id
輔助order_path完成同一級別下的排序
新增資料
有兩種情況:1.新增根結點 2.新增子節點
1.新增根結點
需要注意,parent_path=『0,』 ,2.新增子節點level=』0』 ,
order_id,'select max(order_id) as morder_id from info_class where parent_id=0』 ,morder_id存在,則order_id=morder_id+1,否則order_id=1 ,
order_path等於order_id前面補零,湊足四位。每乙個級別4位的編碼,可以存放0001~9999個分類,完全足夠使用。
需要注意,parent_path=父節點的parent_path+父節點的id+『,' ,**如下:level,通過把parent_path轉換為陣列,得到陣列長度來計算級別 ,
order_id,'select max(order_id) as morder_id from info_class where parent_id=父節點』 ,morder_id存在,則order_id=morder_id+1,否則order_id=1
order_path=父節點的order_path+order_id補零4位
function insert()else
$continue_add=$this->input->post('continue_add');
if($this->info_class_model->addclass($data))
redirect('index.php/submit_success','refresh');
}}
修改資料
有三種情況,1.根結點、或公升級為根結點 2.不更改父節點 3.更改父節點
1.根結點、或公升級為根結點
需要注意,parent_id=0 ,2.不更改父節點parent_path=』0,』 ,
level=0 ,
如果是公升級為根節點:
order_id,'select max(order_id) as morder_id from info_class where parent_id=0』 ,morder_id存在,則order_id=morder_id+1,否則order_id=1 ,
order_path等於order_id前面補零,湊足四位。每乙個級別4位的編碼,可以存放0001~9999個分類,完全足夠使用。
需要注意,parent_path=父節點的parent_path+父節點的id+『,' ,3.更改父節點level,通過把parent_path轉換為陣列,得到陣列長度來計算級別 ,
需要注意,parent_path=父節點的parent_path+父節點的id+『,' ,**如下:level,通過把parent_path轉換為陣列,得到陣列長度來計算級別 ,
///old_order_path=該節點的原order_path,如果該節點有子節點,修改成功後,將子節點的order_path中old_order_path部分替換為新生成的order_path
order_id,'select max(order_id) as morder_id from info_class where parent_id=新父節點』 ,morder_id存在,則order_id=morder_id+1,否則order_id=1
temp_order_path等於order_id前面補零,湊足四位。
order_path=新父節點的order_path+temp_order_path
function update($id)}else
}if($this->info_class_model->updateclass($data))
redirect('index.php/submit_success','refresh');
}}
上移下移、或插入
只能在同一級別內,進行上移下移、或插入
1.上移
假設待上移節點為currentnode2.下移、插入根據currentnode獲取上乙個節點,再根據上乙個節點,獲取上上乙個節點就是待插入位置的節點,假設為brothernode,然後就可以把currentnode上移到brothernode之下了。
接下來,
獲取currentnode的父節點的order_path,假設為father_order_path
設定currentnode的order_id=brothernode的order_id+1
設定currentnode的order_path=father_order_path+currentnode的order_id補零四位
設定currentnode同一級別的其他節點,滿足order_id大於brothernode的order_id(不包括currentnode)條件的節點,order_id+1,order_path=father_order_path+order_id補零四位。
下移、插入都是在某乙個節點下插入,區別是下移是在下乙個節點下插入,而插入是選擇在某一節點下插入
獲取待下移節點為currentnode上移和 下移、插入演算法基本一致,只有獲取待插入位置節點稍微有點不同。獲取待插入位置的節點為brothernode
接下來,
獲取currentnode父節點的order_path,假設為father_order_path
設定currentnode的order_id=brothernode的order_id+1
設定currentnode的order_path=father_order_path+currentnode的order_id補零四位
設定currentnode同一級別的其他節點,滿足order_id大於brothernode的order_id(不包括currentnode)條件的節點,order_id+1,order_path=father_order_path+order_id補零四位。
查詢資料
select * from mini_info_class order by order_path
idparent_id
parent_path
name
order_path
order_id
level200
0,天庭
0022027
200,20,
日遊神00200111
600,冥府
0044026
60,6,
鬼差00400221
1100,妖域
005507
00,魔界00660
1200,人間道
0077029
00,修羅道00880
2829
0,29,
阿修羅00800111
PHP無限級分類實現(遞迴 非遞迴)
created by phpstorm.user qishou date 15 8 2 time 上午12 00 準備陣列,代替從資料庫中檢索出的資料 共有三個必須欄位id,name,pid header content type text html charset utf 8 categories...
PHP無限級分類實現(遞迴 非遞迴)
created by phpstorm.user qishou date 15 8 2 time 上午12 00 準備陣列,代替從資料庫中檢索出的資料 共有三個必須欄位id,name,pid header content type text html charset utf 8 categories...
PHP無限級分類實現(遞迴 非遞迴)
created by phpstorm.user qishou date 15 8 2 time 上午12 00 準備陣列,代替從資料庫中檢索出的資料 共有三個必須欄位id,name,pid header content type text html charset utf 8 categories...