当前位置:首页 > PHP教程 > php高级应用 > 列表

实现PHP+Mysql无限分类的方法

发布:smiling 来源: PHP粉丝网  添加日期:2022-07-26 11:28:12 浏览: 评论:0 

无限分类是个老话题了,来看看PHP结合Mysql如何实现。

第一种方法

这种方法是很常见、很传统的一种,先看表结构

表:category

id int 主键,自增

name varchar 分类名称

pid int 父类id,默认0

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

先来构建一个原始数组,这个直接从数据库中拉出来就行:

代码如下:

  1. $categories = array
  2.  
  3.     array('id'=>1,'name'=>'电脑','pid'=>0), 
  4.  
  5.     array('id'=>2,'name'=>'手机','pid'=>0), 
  6.  
  7.     array('id'=>3,'name'=>'笔记本','pid'=>1), 
  8.  
  9.     array('id'=>4,'name'=>'台式机','pid'=>1), 
  10.  
  11.     array('id'=>5,'name'=>'智能机','pid'=>2), 
  12.  
  13.     array('id'=>6,'name'=>'功能机','pid'=>2), 
  14.  
  15.     array('id'=>7,'name'=>'超级本','pid'=>3), 
  16.  
  17.     array('id'=>8,'name'=>'游戏本','pid'=>3), 
  18.  
  19. ); 

目标是将它转化为下面这种结构

电脑

笔记本

超级本

游戏本

台式机

手机

智能机

功能机

用数组来表示的话,可以增加一个 children 键来存储它的子分类:

代码如下:

  1. array
  2.  
  3.     //1对应id,方便直接读取 
  4.  
  5.     1 => array
  6.  
  7.         'id'=>1, 
  8.  
  9.         'name'=>'电脑'
  10.  
  11.         'pid'=>0, 
  12.  
  13.         children=>array
  14.  
  15.             &array
  16.  
  17.                 'id'=>3, 
  18.  
  19.                 'name'=>'笔记本'
  20.  
  21.                 'pid'=>1, 
  22.  
  23.                 'children'=>array
  24.  
  25.                     //此处省略 
  26.  
  27.                 ) 
  28.  
  29.             ), 
  30.  
  31.             &array
  32.  
  33.                 'id'=>4, 
  34.  
  35.                 'name'=>'台式机'
  36.  
  37.                 'pid'=>1, 
  38.  
  39.                 'children'=>array
  40.  
  41.                     //此处省略 
  42.  
  43.                 ) 
  44.  
  45.             ), 
  46.  
  47.         ) 
  48.  
  49.     ), 
  50.  
  51.     //其他分类省略 
  52.  

处理过程:

代码如下:

  1. $tree = array(); 
  2.  
  3. //第一步,将分类id作为数组key,并创建children单元 
  4.  
  5. foreach($categories as $category){ 
  6.  
  7.     $tree[$category['id']] = $category
  8.  
  9.     $tree[$category['id']]['children'] = array(); 
  10.  
  11.  
  12. //第二部,利用引用,将每个分类添加到父类children数组中,这样一次遍历即可形成树形结构。 
  13.  
  14. foreach ($tree as $k=>$item) { 
  15.  
  16.     if ($item['pid'] != 0) { 
  17.  
  18.         $tree[$item['pid']]['children'][] = &$tree[$k]; 
  19.  
  20.     } 
  21.  
  22.  
  23. print_r($tree); 

打印结果如下:

  1. Array 
  2.  
  3.  
  4.     [1] => Array 
  5.  
  6.         ( 
  7.  
  8.             [id] => 1 
  9.  
  10.             [name] => 电脑 
  11.  
  12.             [pid] => 0 
  13.  
  14.             [children] => Array 
  15.  
  16.                 ( 
  17.  
  18.                     [0] => Array 
  19.  
  20.                         ( 
  21.  
  22.                             [id] => 3 
  23.  
  24.                             [name] => 笔记本 
  25.  
  26.                             [pid] => 1 
  27.  
  28.                             [children] => Array 
  29.  
  30.                                 ( 
  31.  
  32.                                     [0] => Array 
  33.  
  34.                                         ( 
  35.  
  36.                                             [id] => 7 
  37.  
  38.                                             [name] => 超级本 
  39.  
  40.                                             [pid] => 3 
  41.  
  42.                                             [children] => Array 
  43.  
  44.                                                 ( 
  45.  
  46.                                                 ) 
  47.  
  48.                                         ) 
  49.  
  50.                                     [1] => Array 
  51.  
  52.                                         ( 
  53.  
  54.                                             [id] => 8 
  55.  
  56.                                             [name] => 游戏本 
  57.  
  58.                                             [pid] => 3 
  59.  
  60.                                             [children] => Array 
  61.  
  62.                                                 ( 
  63.  
  64.                                                 ) 
  65.  
  66.                                         ) 
  67.  
  68.                                 ) 
  69.  
  70.                         ) 
  71.  
  72.                     [1] => Array 
  73.  
  74.                         ( 
  75.  
  76.                             [id] => 4 
  77.  
  78.                             [name] => 台式机 
  79.  
  80.                             [pid] => 1 
  81.  
  82.                             [children] => Array 
  83.  
  84.                                 ( 
  85.  
  86.                                 ) 
  87.  
  88.                         ) 
  89.  
  90.                 ) 
  91.  
  92.         ) 
  93.  
  94.     [2] => Array 
  95.  
  96.         ( 
  97.  
  98.             [id] => 2 
  99.  
  100.             [name] => 手机 
  101.  
  102.             [pid] => 0 
  103.  
  104.             [children] => Array 
  105.  
  106.                 ( 
  107.  
  108.                     [0] => Array 
  109.  
  110.                         ( 
  111.  
  112.                             [id] => 5 
  113.  
  114.                             [name] => 智能机 
  115.  
  116.                             [pid] => 2 
  117.  
  118.                             [children] => Array 
  119.  
  120.                                 ( 
  121.  
  122.                                 ) 
  123.  
  124.                         ) 
  125.  
  126.                     [1] => Array 
  127.  
  128.                         ( 
  129.  
  130.                             [id] => 6 
  131.  
  132.                             [name] => 功能机 
  133.  
  134.                             [pid] => 2 
  135.  
  136.                             [children] => Array 
  137.  
  138.                                 ( 
  139.  
  140.                                 ) 
  141.  
  142.                         ) 
  143.  
  144.                 ) 
  145.  
  146.         ) 
  147.  
  148.     [3] => Array 
  149.  
  150.         ( 
  151.  
  152.             [id] => 3 
  153.  
  154.             [name] => 笔记本 
  155.  
  156.             [pid] => 1 
  157.  
  158.             [children] => Array 
  159.  
  160.                 ( 
  161.  
  162.                     [0] => Array 
  163.  
  164.                         ( 
  165.  
  166.                             [id] => 7 
  167.  
  168.                             [name] => 超级本 
  169.  
  170.                             [pid] => 3 
  171.  
  172.                             [children] => Array 
  173.  
  174.                                 ( 
  175.  
  176.                                 ) 
  177.  
  178.                         ) 
  179.  
  180.                     [1] => Array 
  181.  
  182.                         ( 
  183.  
  184.                             [id] => 8 
  185.  
  186.                             [name] => 游戏本 
  187.  
  188.                             [pid] => 3 
  189.  
  190.                             [children] => Array 
  191.  
  192.                                 ( 
  193.  
  194.                                 ) 
  195.  
  196.                         ) 
  197.  
  198.                 ) 
  199.  
  200.         ) 
  201.  
  202.     [4] => Array 
  203.  
  204.         ( 
  205.  
  206.             [id] => 4 
  207.  
  208.             [name] => 台式机 
  209.  
  210.             [pid] => 1 
  211.  
  212.             [children] => Array 
  213.  
  214.                 ( 
  215.  
  216.                 ) 
  217.  
  218.         ) 
  219.  
  220.     [5] => Array 
  221.  
  222.         ( 
  223.  
  224.             [id] => 5 
  225.  
  226.             [name] => 智能机 
  227.  
  228.             [pid] => 2 
  229.  
  230.             [children] => Array 
  231.  
  232.                 ( 
  233.  
  234.                 ) 
  235.  
  236.         ) 
  237.  
  238.     [6] => Array 
  239.  
  240.         ( 
  241.  
  242.             [id] => 6 
  243.  
  244.             [name] => 功能机 
  245.  
  246.             [pid] => 2 
  247.  
  248.             [children] => Array 
  249.  
  250.                 ( 
  251.  
  252.                 ) 
  253.  
  254.         ) 
  255.  
  256.     [7] => Array 
  257.  
  258.         ( 
  259.  
  260.             [id] => 7 
  261.  
  262.             [name] => 超级本 
  263.  
  264.             [pid] => 3 
  265.  
  266.             [children] => Array 
  267.  
  268.                 ( 
  269.  
  270.                 ) 
  271.  
  272.         ) 
  273.  
  274.     [8] => Array 
  275.  
  276.         ( 
  277.  
  278.             [id] => 8 
  279.  
  280.             [name] => 游戏本 
  281.  
  282.             [pid] => 3 
  283.  
  284.             [children] => Array 
  285.  
  286.                 ( 
  287.  
  288.                 ) 
  289.  
  290.         ) 
  291.  

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

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

第二种方法

这种方法是在表字段中增加一个path字段:

表:category

id int 主键,自增

name varchar 分类名称

pid int 父类id,默认0

path varchar 路径

示例数据:

id name pid path

1 电脑 0 0

2 手机 0 0

3 笔记本 1 0-1

4 超级本 3 0-1-3

5 游戏本 3 0-1-3

path字段记录了从根分类到上一级父类的路径,用id+'-'表示。

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

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

结果:

  1. +----+-----------+-------+ 
  2. | id | name | path | 
  3. +----+-----------+-------+ 
  4. | 3 | 笔记本 | 0-1 | 
  5. | 4 | 超级本 | 0-1-3 | 
  6. | 5 | 游戏本 | 0-1-3 | 
  7. +----+-----------+-------+ 

这种方式也被很多人所采纳,我总结了下:

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

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

Tags: PHP+Mysql无限分类

分享到: