php递归实现无限级分类树
无限级树状图可以说是无限级栏目的一个显著特征,我们接下来就来看看两种不同的写法。
一.数据库设计
1 CREATE TABLE `bg_cate` ( 2 `cate_Id` int(30) unsigned NOT NULL AUTO_INCREMENT, 3 `cate_ParentId` int(30) unsigned DEFAULT '0', 4 `cate_Name` varchar(100) NOT NULL, 5 `cate_Intro` varchar(500) DEFAULT NULL, 6 `cate_Order` int(30) unsigned DEFAULT '0', 7 `cate_Icon` varchar(100) DEFAULT NULL, 8 PRIMARY KEY (`cate_Id`) 9 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=34 ; 10 -- 11 -- 导出表中的数据 `bg_cate` 12 -- 13 INSERT INTO `bg_cate` (`cate_Id`, `cate_ParentId`, `cate_Name`, `cate_Intro`, `cate_Order`, `cate_Icon`) VALUES 14 (4, 0, '往事如风', '记录往事', 0, 'icons/6.gif'), 15 (5, 0, '水煮三国', '品位三国智慧', 0, 'icons/3.gif'), 16 (2, 0, '技术学习', '平时学习的一些笔记,欢迎批评指正。', 0, 'icons/18.gif'), 17 (3, 0, '生活点滴', '记录生活点滴', 0, 'icons/2.gif'), 18 (6, 0, '栀子花开', '青春无限', 0, 'icons/8.gif'), 19 (7, 0, '假日休闲', '悠闲、自在', 0, 'icons/24.gif'), 20 (8, 2, 'html', 'html学习', 0, 'icons/1.gif'), 21 (9, 2, 'css', 'css学习', 0, 'icons/1.gif'), 22 (10, 2, 'php', 'php学习', 0, 'icons/18.gif'), 23 (11, 10, 'php基础知识', 'php基础知识', 0, 'icons/1.gif'), 24 (12, 10, 'oop', 'oop', 0, 'icons/1.gif'), 25 (13, 10, 'php安全', '讲述php安全', 0, 'icons/1.gif'), 26 (14, 10, 'seagull framework', 'seagull framework', 0, 'icons/1.gif'), 27 (15, 2, 'javascript', 'javascript学习', 0, 'icons/1.gif'), 28 (16, 2, '设计模式', NULL, 0, 'icons/1.gif'), 29 (17, 2, '软件工程', '软件工程学习', 0, 'icons/1.gif'), 30 (18, 3, '厦门生活', '厦门生活', 0, 'icons/8.gif'), 31 (19, 3, '大学生活', '大学生活', 0, 'icons/8.gif'), 32 (20, 3, '童年生活', '童年生活', 0, 'icons/15.gif'), 33 (21, 19, '学习', '学习', 0, 'icons/1.gif'), 34 (22, 19, '运动', '运动', 0, 'icons/16.gif'), 35 (23, 19, '旅游', '旅游', 0, 'icons/24.gif'), 36 (24, 22, '排球', '排球', 0, 'icons/9.gif'), 37 (25, 22, '篮球', '篮球', 0, 'icons/9.gif'), 38 (26, 22, '羽毛球', '羽毛球', 0, 'icons/9.gif'), 39 (27, 22, '乒乓球', '乒乓球', 0, 'icons/9.gif');
二.到数据库取数据,放到数组。
1 require_once './classes/MyDB.php'; 2 $con = MyDB::singleton(); 3 $sql = <<<SQL 4 select * from bg_cate cate 5 SQL; 6 $data = $con->getAll($sql); 7 //print_r($data);
数据库操作我用的是pear类库。
最后的$data的数据格式如下:
1 Array 2 ( 3 [0] => Array 4 ( 5 [cate_Id] => 4 6 [cate_ParentId] => 0 7 [cate_Name] => 往事如风 8 [cate_Intro] => 记录往事 9 [cate_Order] => 0 10 [cate_Icon] => icons/6.gif 11 ) 12 [1] => Array 13 ( 14 [cate_Id] => 5 15 [cate_ParentId] => 0 16 [cate_Name] => 水煮三国 17 [cate_Intro] => 品位三国智慧 18 [cate_Order] => 0 19 [cate_Icon] => icons/3.gif 20 )
三.把上一步的数据转为树型状的数组
代码如下:
1 function getTree($data, $pId) 2 { 3 $tree = ''; 4 foreach($data as $k => $v) 5 { 6 if($v['cate_ParentId'] == $pId) 7 { //父亲找到儿子 8 $v['cate_ParentId'] = getTree($data, $v['cate_Id']); 9 $tree[] = $v; 10 //unset($data[$k]); 11 } 12 } 13 return $tree; 14 } 15 $tree = getTree($data, 0);
最后输出$tree的数据格式为:
1 Array 2 ( 3 [0] => Array 4 ( 5 [cate_Id] => 4 6 [cate_ParentId] => 7 [cate_Name] => 往事如风 8 [cate_Intro] => 记录往事 9 [cate_Order] => 0 10 [cate_Icon] => icons/6.gif 11 ) 12 [1] => Array 13 ( 14 [cate_Id] => 5 15 [cate_ParentId] => 16 [cate_Name] => 水煮三国 17 [cate_Intro] => 品位三国智慧 18 [cate_Order] => 0 19 [cate_Icon] => icons/3.gif 20 ) 21 [2] => Array 22 ( 23 [cate_Id] => 2 24 [cate_ParentId] => Array 25 ( 26 [0] => Array 27 ( 28 [cate_Id] => 8 29 [cate_ParentId] => 30 [cate_Name] => html 31 [cate_Intro] => html学习 32 [cate_Order] => 0 33 [cate_Icon] => icons/1.gif 34 )
四.把树型状数组转为html
代码如下:
1 function procHtml($tree) 2 { 3 $html = ''; 4 foreach($tree as $t) 5 { 6 if($t['cate_ParentId'] == '') 7 { 8 $html .= "<li>{$t['cate_Name']}</li>"; 9 } 10 else 11 { 12 $html .= "<li>".$t['cate_Name']; 13 $html .= procHtml($t['cate_ParentId']); 14 $html = $html."</li>"; 15 } 16 } 17 return $html ? '<ul>'.$html.'</ul>' : $html ; 18 } 19 echo procHtml($tree);
输出的html的代码格式为:
1 <ul> 2 <li>往事如风</li> 3 <li>水煮三国</li> 4 <li>技术学习 5 <ul> 6 <li>html</li> 7 <li>css</li> 8 <li>php 9 <ul> 10 <li>php基础知识</li> 11 <li>oop</li> 12 <li>php安全</li>
五.代码整合
1 function getTree($data, $pId) 2 { 3 $html = ''; 4 foreach($data as $k => $v) 5 { 6 if($v['cate_ParentId'] == $pId) 7 { //父亲找到儿子 8 $html .= "<li>".$v['cate_Name']; 9 $html .= getTree($data, $v['cate_Id']); 10 $html = $html."</li>"; 11 } 12 } 13 return $html ? '<ul>'.$html.'</ul>' : $html ; 14 } 15 echo getTree($data, 0);
六.增加CSS样式
第二种是从开源网站上看到的,非常非常的简介。
1 <?php 2 3 function genTree5($items) { 4 foreach ($items as $item) 5 $items[$item['pid']]['son'][$item['id']] = &$items[$item['id']]; 6 return isset($items[0]['son']) ? $items[0]['son'] : array(); 7 } 8 9 /** 10 * 将数据格式化成树形结构 11 * @author Xuefen.Tong 12 * @param array $items 13 * @return array 14 */ 15 function genTree9($items) { 16 $tree = array(); //格式化好的树 17 foreach ($items as $item) 18 if (isset($items[$item['pid']])) 19 $items[$item['pid']]['son'][] = &$items[$item['id']]; 20 else 21 $tree[] = &$items[$item['id']]; 22 return $tree; 23 } 24 25 $items = array( 26 1 => array('id' => 1, 'pid' => 0, 'name' => '江西省'), 27 2 => array('id' => 2, 'pid' => 0, 'name' => '黑龙江省'), 28 3 => array('id' => 3, 'pid' => 1, 'name' => '南昌市'), 29 4 => array('id' => 4, 'pid' => 2, 'name' => '哈尔滨市'), 30 5 => array('id' => 5, 'pid' => 2, 'name' => '鸡西市'), 31 6 => array('id' => 6, 'pid' => 4, 'name' => '香坊区'), 32 7 => array('id' => 7, 'pid' => 4, 'name' => '南岗区'), 33 8 => array('id' => 8, 'pid' => 6, 'name' => '和兴路'), 34 9 => array('id' => 9, 'pid' => 7, 'name' => '西大直街'), 35 10 => array('id' => 10, 'pid' => 8, 'name' => '东北林业大学'), 36 11 => array('id' => 11, 'pid' => 9, 'name' => '哈尔滨工业大学'), 37 12 => array('id' => 12, 'pid' => 8, 'name' => '哈尔滨师范大学'), 38 13 => array('id' => 13, 'pid' => 1, 'name' => '赣州市'), 39 14 => array('id' => 14, 'pid' => 13, 'name' => '赣县'), 40 15 => array('id' => 15, 'pid' => 13, 'name' => '于都县'), 41 16 => array('id' => 16, 'pid' => 14, 'name' => '茅店镇'), 42 17 => array('id' => 17, 'pid' => 14, 'name' => '大田乡'), 43 18 => array('id' => 18, 'pid' => 16, 'name' => '义源村'), 44 19 => array('id' => 19, 'pid' => 16, 'name' => '上坝村'), 45 ); 46 echo "<pre>"; 47 print_r(genTree5($items)); 48 print_r(genTree9($items)); 49 50 //后者输出格式,前者类似,只是数组键值不一样,不过不影响数据结构 51 /* 52 Array 53 ( 54 [0] => Array 55 ( 56 [id] => 1 57 [pid] => 0 58 [name] => 江西省 59 [son] => Array 60 ( 61 [0] => Array 62 ( 63 [id] => 3 64 [pid] => 1 65 [name] => 南昌市 66 ) 67 68 [1] => Array 69 ( 70 [id] => 13 71 [pid] => 1 72 [name] => 赣州市 73 [son] => Array 74 ( 75 [0] => Array 76 ( 77 [id] => 14 78 [pid] => 13 79 [name] => 赣县 80 [son] => Array 81 ( 82 [0] => Array 83 ( 84 [id] => 16 85 [pid] => 14 86 [name] => 茅店镇 87 [son] => Array 88 ( 89 [0] => Array 90 ( 91 [id] => 18 92 [pid] => 16 93 [name] => 义源村 94 ) 95 96 [1] => Array 97 ( 98 [id] => 19 99 [pid] => 16 100 [name] => 上坝村 101 ) 102 103 ) 104 105 ) 106 107 [1] => Array 108 ( 109 [id] => 17 110 [pid] => 14 111 [name] => 大田乡 112 ) 113 114 ) 115 116 ) 117 118 [1] => Array 119 ( 120 [id] => 15 121 [pid] => 13 122 [name] => 于都县 123 ) 124 125 ) 126 127 ) 128 129 ) 130 131 ) 132 133 [1] => Array 134 ( 135 [id] => 2 136 [pid] => 0 137 [name] => 黑龙江省 138 [son] => Array 139 ( 140 [0] => Array 141 ( 142 [id] => 4 143 [pid] => 2 144 [name] => 哈尔滨市 145 [son] => Array 146 ( 147 [0] => Array 148 ( 149 [id] => 6 150 [pid] => 4 151 [name] => 香坊区 152 [son] => Array 153 ( 154 [0] => Array 155 ( 156 [id] => 8 157 [pid] => 6 158 [name] => 和兴路 159 [son] => Array 160 ( 161 [0] => Array 162 ( 163 [id] => 10 164 [pid] => 8 165 [name] => 166 东北林业大学 167 ) 168 169 [1] => Array 170 ( 171 [id] => 12 172 [pid] => 8 173 [name] => 174 哈尔滨师范大学 175 ) 176 177 ) 178 179 ) 180 181 ) 182 183 ) 184 185 [1] => Array 186 ( 187 [id] => 7 188 [pid] => 4 189 [name] => 南岗区 190 [son] => Array 191 ( 192 [0] => Array 193 ( 194 [id] => 9 195 [pid] => 7 196 [name] => 西大直街 197 [son] => Array 198 ( 199 [0] => Array 200 ( 201 [id] => 11 202 [pid] => 9 203 [name] => 204 哈尔滨工业大学 205 ) 206 207 ) 208 209 ) 210 211 ) 212 213 ) 214 215 ) 216 217 ) 218 219 [1] => Array 220 ( 221 [id] => 5 222 [pid] => 2 223 [name] => 鸡西市 224 ) 225 226 ) 227 228 ) 229 )*/
可以看出第二种代码只用了5行代码就实现了无限级的分类树,非常值得大家的借鉴和学习
文章转自:http://www.php.cn/php-weizijiaocheng-353267.html