無限級分類是所有程序開發中會碰到的一個問題,下面我來介紹php+mysql實現的一個無限級分類程序,有需要的朋友可參考參考,下面給大家看看我的數據庫結構吧,數據庫的名字為 fa_category
Field Type Comment
cid int(11) 分類id
catename varchar(255) 分類名字
catetype int(1) 分類類型,1為單頁面,2為普通分類
catdir varchar(255) 英文目錄
display int(1) 1為顯示,2為不顯示
keywords varchar(255) 欄目關鍵字
description text 欄目描述
ctime int(11) 創建時間
parentid int(11) 父節點id,最高節點父節點為0
我們使用一個parentid字段來記錄父節點的id,如果parentid為0,則為root,不多說,我們看看代碼怎么寫吧,我們要實現的功能就是如圖片所示:

怎么樣把它這樣顯示呢?這個問題我想了很久,先看看這段SQL語句吧,代碼如下:
- SELECT c.cat_id, c.cat_name, c.measure_unit, c.parent_id, c.is_show, c.show_in_nav, c.grade ,c.sort_order, COUNT( s.cat_id ) AS has_children
- FROM ecs_category AS c
- LEFT JOIN ecs_category AS s ON s.parent_id = c.cat_id
- GROUP BY c.cat_id
- ORDER BY c.parent_id, c.sort_order ASC
用左連接連接一個表,返回一個字段 has_children,這個字段是記錄有多少子節點,看看代碼吧:
- public function getCategory($catid=0,$re_type = true,$selected=0)
- {
- $db = new Public_DataBase();
- $sql = 'select c.cid,c.catename,c.catetype,c.ctime,c.parentid,count(s.cid) as has_children from '.
- __MYSQL_PRE.'category as c left join '.
- __MYSQL_PRE.'category as s on s.parentid=c.cid group by c.cid order by c.parentid asc';
- $res = $db->selectTable($sql);
- $cateInfo = self::getChildTree($catid,$res);
- if($re_type==true)
- {
- $select = '';
- foreach($cateInfo as $val)
- {
- $select .= '<option value="' . $val['cid'] . '" ';
- $select .= ($selected == $val['cid']) ? "selected='ture'" : '';
- $select .= '>';
- if($val['level']>0)
- {
- $select .= str_repeat(' ', $val['level'] * 4);
- }
- $select .= htmlspecialchars(addslashes($val['catename']), ENT_QUOTES) . '</option>';
- }
- return $select;
- }
- else
- {
- foreach($cateInfo as $key=>$val)
- {
- if($val['level']>0)
- {
- $cateInfo[$key]['catename'] = "|".str_repeat(' ', $val['level'] * 8)."└─".$val['catename'];
- }
- }
- return $cateInfo;
- }
- }
- /**
- * 通過父ID遞歸得到所有子節點樹
- * @param int $catid 上級分類
- * @param array $arr 含有所有分類的數組
- * @return array
- */
- public function getChildTree($catid,$arr)
- {
- $level = $last_cat_id = 0;
- while (!emptyempty($arr))
- {
- foreach($arr as $key=>$value)
- {
- $cid = $value['cid'];
- if ($level == 0 && $last_cat_id == 0)
- {
- if ($value['parentid'] > 0)
- {
- break;
- }
- $options[$cid] = $value;
- $options[$cid]['level'] = $level;
- $options[$cid]['id'] = $cid;
- $options[$cid]['name'] = $value['catename'];
- unset($arr[$key]);
- if ($value['has_children'] == 0)
- {
- continue;
- }
- $last_cat_id = $cid;
- $cat_id_array = array($cid);
- $level_array[$last_cat_id] = ++$level;
- continue;
- }
- if ($value['parentid'] == $last_cat_id)
- {
- $options[$cid] = $value;
- $options[$cid]['level'] = $level;
- $options[$cid]['id'] = $cid;
- $options[$cid]['name'] = $value['catename'];
- unset($arr[$key]);
- if ($value['has_children'] > 0)
- {
- if (end($cat_id_array) != $last_cat_id)
- {
- $cat_id_array[] = $last_cat_id;
- }
- $last_cat_id = $cid;
- $cat_id_array[] = $cid;
- $level_array[$last_cat_id] = ++$level;
- }
- }
- elseif ($value['parentid'] > $last_cat_id)
- {
- break;
- }
- }
- $count = count($cat_id_array);
- if ($count > 1)
- {
- $last_cat_id = array_pop($cat_id_array);
- }
- elseif ($count == 1)
- {
- if ($last_cat_id != end($cat_id_array))
- {
- $last_cat_id = end($cat_id_array);
- }
- else
- {
- $level = 0;
- $last_cat_id = 0;
- $cat_id_array = array();
- continue;
- }
- }
- if ($last_cat_id && isset($level_array[$last_cat_id]))
- {
- $level = $level_array[$last_cat_id];
- }
- else
- {
- $level = 0;
- }
- }
- return $options;
- }
用smarty的一個循環就可以把它顯示出來,效果和上面圖片的一樣!大家有什么問題可以給我留言。
新聞熱點
疑難解答