PHP+MySQL 无限级分类的两种实现方案

来源:互联网 发布:foxmail导入旧数据 编辑:程序博客网 时间:2024/05/06 14:55

方案一:

表结构:

id int primary key auto_increment;

name varchar(40);

pid int default 0; #父类id,默认值为0

顶级分类的 pid 默认就是0了。当我们想取出某个分类的子分类树的时候,基本思路就是递归,当然,出于效率问题不建议每次递归都查询数据库,通常的做法是先将所有分类取出来,保存到PHP数组里,再进行处理,最后还可以将结果缓存起来以提高下次请求的效率。

优点:关系清楚,修改上下级关系简单

缺点:使用PHP处理,如果分类信息数量庞大,效率也会降低


方案二:

在表字段中增加一个 path 字段

id int primary key auto_increment;

name varchar(40);

pid int default 0; #父类id,默认值为0

path varchar(255); #记录从根分类到父类的路径,eg:0-1-5,数字是id

示例数据:

id        name        pid        path

1         电脑         0           0

2         手机         0           0

3         笔记本     1           0-1

4         超级本     3           0-1-3

5         游戏本     3           0-1-3

这种方式,假设我们要查询电脑下的所有后代分类,只需要一条sql语句:

select id,name from category where path like ( select concat(path,'-',id,'%') path from category where id=1 );

优点:查询容易,效率高,path字段可以加索引。

缺点:更新节点关系麻烦,需要更新所有后辈的path字段。


方案一的样例代码:

<?php

$addrs = array(

    array('id'=>1, 'name'=>'中国', 'pid'=>0),

    array('id'=>2, 'name'=>'河南', 'pid'=>1),

    array('id'=>3, 'name'=>'郑州', 'pid'=>2),

    array('id'=>4, 'name'=>'洛阳', 'pid'=>2),

    array('id'=>5, 'name'=>'安阳', 'pid'=>2),

    array('id'=>6, 'name'=>'林州', 'pid'=>5),

    array('id'=>7, 'name'=>'安阳县', 'pid'=>5),

    array('id'=>8, 'name'=>'内黄', 'pid'=>5),

    array('id'=>9, 'name'=>'滑县', 'pid'=>5),

    array('id'=>10, 'name'=>'城郊乡', 'pid'=>6),

    array('id'=>11, 'name'=>'湖南', 'pid'=>1),

    array('id'=>12, 'name'=>'长沙', 'pid'=>11),

    array('id'=>13, 'name'=>'湘潭', 'pid'=>11),

    array('id'=>14, 'name'=>'岳麓区', 'pid'=>12),

);

// 查询子树

function get_childs($id)

{

    global $addrs;

    $ret = array();

    foreach($addrs as &$addr)  // 此处使用 & 运算符,提高效率

    {

        if($addr['pid'] == $id)

        {

            $addr['children'] = get_childs($addr['id']);

            $ret[] = $addr;

        }

    }

    return $ret;

}

// test code

echo '<pre>';

print_r( get_childs(1) );

echo '<hr/>';

print_r($addrs);


0 0
原创粉丝点击