当前位置:首页 > 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.  
  53. ) 

处理过程:

代码如下:

  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.  
  13. //第二部,利用引用,将每个分类添加到父类children数组中,这样一次遍历即可形成树形结构。 
  14.  
  15. foreach ($tree as $k=>$item) { 
  16.  
  17.     if ($item['pid'] != 0) { 
  18.  
  19.         $tree[$item['pid']]['children'][] = &$tree[$k]; 
  20.  
  21.     } 
  22.  
  23. } 
  24.  
  25. print_r($tree); 

打印结果如下:

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

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

缺点:使用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无限分类

分享到: