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还是方法二比较有效!

posted @ 2012-10-07 21:49  无嗔  阅读(4145)  评论(0编辑  收藏  举报