无限分类是个老话题了,来看看PHP结合Mysql如何实现。
第一种方法
这种方法是很常见、很传统的一种,先看表结构
表:categoryid int 主键,自增name varchar 分类名称pid int 父类id,默认0顶级分类的 pid 默认就是0了。当我们想取出某个分类的子分类树的时候,基本思路就是递归,当然,出于效率问题不建议每次递归都查询数据库,通常的做法是先讲所有分类取出来,保存到PHP数组里,再进行处理,最后还可以将结果缓存起来以提高下次请求的效率。
先来构建一个原始数组,这个直接从数据库中拉出来就行:
复制代码 代码如下:$categories = array( array("id"=>1,"name"=>"电脑","pid"=>0), array("id"=>2,"name"=>"手机","pid"=>0), array("id"=>3,"name"=>"笔记本","pid"=>1), array("id"=>4,"name"=>"台式机","pid"=>1), array("id"=>5,"name"=>"智能机","pid"=>2), array("id"=>6,"name"=>"功能机","pid"=>2), array("id"=>7,"name"=>"超级本","pid"=>3), array("id"=>8,"name"=>"游戏本","pid"=>3),);
目标是将它转化为下面这种结构
电脑 笔记本 超级本 游戏本 台式机手机 智能机 功能机用数组来表示的话,可以增加一个 children 键来存储它的子分类:
复制代码 代码如下:array( //1对应id,方便直接读取 1 => array( "id"=>1, "name"=>"电脑", "pid"=>0, children=>array( &array( "id"=>3, "name"=>"笔记本", "pid"=>1, "children"=>array( //此处省略 ) ), &array( "id"=>4, "name"=>"台式机", "pid"=>1, "children"=>array( //此处省略 ) ), ) ), //其他分类省略)
处理过程:
复制代码 代码如下:$tree = array();//第一步,将分类id作为数组key,并创建children单元foreach($categories as $category){ $tree[$category["id"]] = $category; $tree[$category["id"]]["children"] = array();}//第二部,利用引用,将每个分类添加到父类children数组中,这样一次遍历即可形成树形结构。foreach ($tree as $k=>$item) { if ($item["pid"] != 0) { $tree[$item["pid"]]["children"][] = &$tree[$k]; }}print_r($tree);
打印结果如下:
复制代码 代码如下:Array( [1] => Array ( [id] => 1 [name] => 电脑 [pid] => 0 [children] => Array ( [0] => Array ( [id] => 3 [name] => 笔记本 [pid] => 1 [children] => Array ( [0] => Array ( [id] => 7 [name] => 超级本 [pid] => 3 [children] => Array ( ) ) [1] => Array ( [id] => 8 [name] => 游戏本 [pid] => 3 [children] => Array ( ) ) ) ) [1] => Array ( [id] => 4 [name] => 台式机 [pid] => 1 [children] => Array ( ) ) ) ) [2] => Array ( [id] => 2 [name] => 手机 [pid] => 0 [children] => Array ( [0] => Array ( [id] => 5 [name] => 智能机 [pid] => 2 [children] => Array ( ) ) [1] => Array ( [id] => 6 [name] => 功能机 [pid] => 2 [children] => Array ( ) ) ) ) [3] => Array ( [id] => 3 [name] => 笔记本 [pid] => 1 [children] => Array ( [0] => Array ( [id] => 7 [name] => 超级本 [pid] => 3 [children] => Array ( ) ) [1] => Array ( [id] => 8 [name] => 游戏本 [pid] => 3 [children] => Array ( ) ) ) ) [4] => Array ( [id] => 4 [name] => 台式机 [pid] => 1 [children] => Array ( ) ) [5] => Array ( [id] => 5 [name] => 智能机 [pid] => 2 [children] => Array ( ) ) [6] => Array ( [id] => 6 [name] => 功能机 [pid] => 2 [children] => Array ( ) ) [7] => Array ( [id] => 7 [name] => 超级本 [pid] => 3 [children] => Array ( ) ) [8] => Array ( [id] => 8 [name] => 游戏本 [pid] => 3 [children] => Array ( ) ))
优点:关系清楚,修改上下级关系简单。
缺点:使用PHP处理,如果分类数量庞大,效率也会降低。
第二种方法
这种方法是在表字段中增加一个path字段:
表:categoryid int 主键,自增name varchar 分类名称pid int 父类id,默认0path varchar 路径示例数据:
id name pid path1 电脑 0 02 手机 0 03 笔记本 1 0-14 超级本 3 0-1-35 游戏本 3 0-1-3path字段记录了从根分类到上一级父类的路径,用id+"-"表示。
这种方式,假设我们要查询电脑下的所有后代分类,只需要一条sql语句:
select id,name,path from category where path like (select concat(path,"-",id,"%") as path from category where id=1);结果:
+----+-----------+-------+| id | name | path |+----+-----------+-------+| 3 | 笔记本 | 0-1 || 4 | 超级本 | 0-1-3 || 5 | 游戏本 | 0-1-3 |+----+-----------+-------+这种方式也被很多人所采纳,我总结了下:
优点:查询容易,效率高,path字段可以加索引。
缺点:更新节点关系麻烦,需要更新所有后辈的path字段。
以上就是本文的全部内容了,两种方式,你喜欢哪种?希望大家能够喜欢。