php+mysql生成父子树结构
项目中可以经常要生成tree结构, 一般都是从数据库里读父子表,
方式很多种,哪种最好呢? 下面举个示例:
数据库:
1 -- 2 -- 表的结构 `oa_group` 3 -- 4 5 CREATE TABLE IF NOT EXISTS `oa_group` ( 6 `id` int(11) NOT NULL AUTO_INCREMENT, 7 `describe` varchar(50) NOT NULL, 8 `auth` varchar(20) DEFAULT NULL, 9 `parent_id` int(11) NOT NULL DEFAULT '0', 10 PRIMARY KEY (`id`) 11 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=44 ; 12 13 -- 14 -- 转存表中的数据 `oa_group` 15 -- 16 17 INSERT INTO `oa_group` (`id`, `describe`, `auth`, `parent_id`) VALUES 18 (1, ' 管理员', '["all"]', 0), 19 (2, '业务经理', '["1","3"]', 0), 20 (3, '片区主管', '', 0), 21 (4, '业务员', '', 3), 22 (5, '数据查看', '', 1), 23 (6, '录入员', '', 5), 24 (7, '硕放片区', '', 2), 25 (8, '梅村片区', '', 3), 26 (12, '王经理', '', 8), 27 (13, '老王经理', '', 2), 28 (42, '新增组', '', 0), 29 (43, '新增0组', '', 42);
方法一:(递归)
<?php function getSql($sql){ $link = mysql_connect('127.0.0.1','root','wc'); if (!$link) { die('Could not connect to MySQL: ' . mysql_error()); } mysql_select_db("test",$link); mysql_query("SET NAMES utf8"); $result = mysql_query($sql); $data = array(); while($row=mysql_fetch_array($result,1)){ $data[] = $row; } mysql_close($link); return $data; } function toJson($pid=0){ $sql="select id,`describe` as text from oa_group where parent_id={$pid}"; $data = getSql($sql); $jsonData = array(); foreach($data as $v){ $jsonData[$v['id']] = $v; $child = toJson($v['id']); if(!empty($child)) $jsonData[$v['id']]['children'] = array_values($child); } return $jsonData; } print_r((toJson())); //print_r(json_encode(array_values(toJson()))); ?>
这种方法就是简单,一看就懂, 但是效率很低,这样循环的读数据库TCP开销太大.
方法二:(循环)
1 function toJson2(){ 2 $json_data = array(); 3 $sql="select * from oa_group"; 4 $data = getSql($sql); 5 6 foreach($data as $value){ 7 $json_data[$value['id']] = array('id' => $value['id'], 'text' => $value['describe'], 'parent_id' => $value['parent_id']); 8 } 9 foreach($json_data as $v){ 10 unset($json_data[$v['id']]['parent_id']); 11 if($v['parent_id'] != 0){ 12 $json_data[$v['parent_id']]['children'][] = $json_data[$v['id']]; 13 unset($json_data[$v['id']]); 14 } 15 } 16 ksort($json_data); 17 return $json_data; 18 }
这种方法看起来挺好, 可以要两次循环,能不能优化下呢?
方法三:
1 function toJson3(){ 2 $json_data = array(); 3 $sql="select * from oa_group order by id desc"; 4 $data = getSql($sql); 5 //print_r($data); 6 foreach($data as $v){ 7 // $json_data[$value['id']] = array('id' => $value['id'], 'text' => $value['describe'], 'parent_id' => $value['parent_id']); 8 //} 9 //foreach($json_data as $v){ 10 //unset($json_data[$v['id']]['parent_id']); 11 $json_data[$v['id']] = isset($json_data[$v['id']]) ? $v + $json_data[$v['id']] : $v; 12 if($v['parent_id'] != 0){ 13 $json_data[$v['parent_id']]['children'][] = $json_data[$v['id']]; 14 unset($json_data[$v['id']]); 15 } 16 //$json_data[$v['id']] = $v; 17 } 18 ksort($json_data); 19 return $json_data; 20 }
和方法二比,这优化了很多. 但要注意的两者之间的区别:
方法二中的sql语句和方法二比少了一个order by id desc.且parent_id不于id
这很重要,因为方法三中$json_data[$v['parent_id']]['children'][]时如果没有排序id..那么可能这个数据的index还没有生成.
由此可以看出,方法三的局限性在于: parent_id必须比id小.当然一般id自动编号的话这是肯定比它小的,
手工指定的parent_id还是方法二比较有效!