PHP實現無限分類
無限級分類是一種設計技巧,在開發中經常使用,例如:網站目錄、部門結構、文章分類。筆者覺得它在對於設計表的層級結構上面發揮很大的作用,比如大家在一些平台上面,填寫邀請人,它就是一種上下級的關系,上級會有多個下級,下級又會有自己的分支,大多數都是利用遞歸的思想去實現。話不多說,首先來溫故一下遞歸的實現。
遞歸(程序調用自身的編程技巧):
1、$_GLOBALS[result]
2、static $result
3、參數引用&
舉例:遍歷1-10
- $i=0;
- function deeploop( $i ){
- global $i;
- $i++;
- echo $i;
- if( $i<10 ){
- deeploop($i);
- }
- }
- function deeploop( ){
- static $i=0;
- $i++;
- echo $i;
- if( $i<10 ){
- deeploop($i);
- }
- }
- function deeploop( &$i=0 ){
- $i++;
- echo $i;
- if( $i<10 ){
- deeploop($i);
- }
- }
無限分類實現:
1、表設計設置父id 頂級父id設為0 建立族譜樹;每一個分類都需記錄它的父級id。
id pid catename cateorder createtime ( 主鍵id,父id,分類name,分類排序,創建時間)
舉例:網站的分類目錄結構;餐飲的分類結構;評論的結構
2、全路徑無限分類(以一個字段將所有父級id按順序記錄下來)
id path catename cateorder createtime ( 主鍵id,逗號分隔的順序排列父id,分類name,分類排序,創建時間)
優缺點:
全路徑查詢方便;增加,移動分類時數據維護稍顯復雜;
舉例:網站目錄
分類表:
- #父級Id遞歸法
- CREATE TABLE `deepcate`(
- `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
- `Pid` int(11) NOT NULL DEFAULT 0,
- `catename` char(25) NOT NULL,
- `cateorder` int(6) ,
- `createtime` date
- )ENGINE=INNODB default CHARSET=utf8;
-
-
- //數據
- INSERT INTO `deepcate` VALUES(1,0,'圖片',null,'2016-11-01'),
- ( 2,1,'美女',null,'2016-11-01'),
- ( 3,1,'新聞',null,'2016-11-01'),
- ( 4,2,'足球寶貝',null,'2016-11-01'),
- ( 5,2,'日韓明星',null,'2016-11-01'),
- ( 6,5,'美女寫真',null,'2016-11-01');
-
- #全路徑
- CREATE TABLE `qljcate` (
- `id` int(11) NOT NULL,
- `path` char(255) ,
- `catename` char(25) NOT NULL,
- `cateorder` int(6),
- `createtime` date
- )ENGINE=INNODB default CHARSET=utf8;
-
- INSERT INTO `qljcate` VALUES(1,null,'圖片',null,'2016-11-01'),
- ( 2,1,'美女圖片',null,'2016-11-01'), (3,1,2,'足球寶貝',null,'2016-11-01'), (4,1,2,'日韓明星',null,'2016-11-01'),
- (5,1,2,4,'美女寫真',null,'2016-11-01');
-
獲取圖片所在的目錄路徑:
- #父級Id實現法(數據庫連接操作此處就不提及,提供思路,實現看個人調整)
- function GetCatepath( $id,&$result=array() ){
- $sql = "SELECT * FROM deepcate WHERE id={$id}";
- $query = mysql_query( $sql );
- $row = mysql_fetch_assoc( $query );
- if( $row ){
- $result[] = $row;
- GetCatepath( $row['pid'],$result );
- }
- return $result;
- }
-
- #全路徑實現
- function GetCatepath( $id ){
- $sql = "SELECT * FROM qljcate WHERE id in (select contact(path,',',id) from qljcate where id={$id}) ORDER BY id asc";
- $query = mysql_query( $sql );
- $row = mysql_fetch_assoc( $query );
- return $result;
-
- }
-
移動分類不能移到自己及其子類下面;刪除分類 (只能刪除最底層的分類,及不含子類的分類;換言之,只能從最底層刪起)
1)、思考圖片類型下所有的圖片分類?
- #pid 父級id實現法
- function GetAllcate( $id,&$result=array() ){
- $sql = "SELECT * FROM deepcate WHERE pid in ({$id})";
- $query = mysql_query( $sql );
- $row = mysql_fetch_assoc( $query );
- if( mysql_num_rows($row)>0 )
- {
- $idlist = array();
- while( $row ){
- $result[] = $row;
- $idlist[] = $row['id'];
- }
- $id = implode(',',$idlist);
- GetAllcate( $id,$result );
-
- }
- $result = array_unique( $result );
- return $result;
- }
此類方法比較適用於查詢所在父分類下所有的書籍、文章。。。當然,全路徑可以直接獲取,就不再此提出了。
2)、上述的這些查詢操作數據庫的操作可能過於頻繁了,也是可以將數據全部查詢出來(一般這種無限分類數據不會很多的),再用程序處理。
如:工作中我們會遇到聯動的情況,如地址的選擇 省市區。
- #獲取樹形結構數據
- function GetTree( $data=array() ){ //$data數據需處理以id為索引
- foreach( $data as $v){
- $data[$v['id']] = $v;
- }
-
- $level0 = array(); //只需取出頂級的數據(判斷父級id是否等於0 ,子元素放入父元素下面)
- foreach( $data as $val){
- if( $val['pid']!=0 ){
- $data[$val['pid']]['tree'][] = &$data[$val['id']];
-
- }
- else{
- $level0[] = &$data[$val['id']];
- }
- }
- return $level0;
- }
得到樹形接結構數據,可調用下面方法生成ul列表(可調整代碼,修改你想要的頁面效果):
- #顯示分類列表
- function SetUlhtml( $data,$type="checkbox",&$state=1 ){
- $ul = '';
- if( !empty($data) ){
- $ul= '<ul '.(($state++)==1?"id=\"tree\" class=\"treeview\"":'').' >';
- foreach( $data as $v){
- $ul.= ' <li class="biaoshi"><span id="'.$v['id'].'" class="folder">'.$v['name'].'</span>';
- if( $type ) $ul.='<input type="'.$type.'" value="'.$v['id'].'" name="cate">';
- if( $v['tree'] ){
- $ul.= $this->SetUlhtml( $v['tree'],$type,$state );
- }
- $ul.='</li>';
- }
- $ul= $ul.'</ul>';
- }
- return $ul;
- }
實際操作中,我們可以根據實際情況設計合理的表結構。
舉個實例,連鎖門店實現商品的管理,門店的賬戶設置就會存在上下級關系,根據代理點的分區可能存在這種下級擁有自己下級,那么采用這種無限分類的方法就比較靈活面對這種 關系體系,只需設定每個賬戶等級,就能對不同的門店設定權限分配。
希望分享更多技術的文章。。。