用数组和递归提高php无限分类查询的效率

有这样一个数据库 fruit
三个字段id , parentid ,name,如何查询完所有分类(包括父分类和子分类)?

地球人都知道的方法:

先查询最顶级的分类,select * from fruit where parentid=0.

得到顶级分类的id,然后用递归的方法,根据父id查询子分类。但是这样会查询很多次数据库,而且分类越多,查询的次数增长得越快。

设想要是有10个人同时查询所有分类,而这个分类有4层,每层有10个子分类,估计你的数据库忙不过来。

下面给出一个很实用的方法,这个方法其实是把本来数据库做的工作交给了程序处理,一次性查询完所有分类。

下面是代码,一个class

<?php 
class Tree { 
 /** 
  * 从数据库查询出的所有分类信息 
  * @var array 
  */
 var $arr; 
/** 
 * 如下格式 
 *  var $arr = array( 
 1 => array(‘id’=>’1′,’parentid’=>0,’name’=>’一级栏目一’), 
 2 => array(‘id’=>’2′,’parentid’=>0,’name’=>’一级栏目二’), 
 3 => array(‘id’=>’3′,’parentid’=>1,’name’=>’二级栏目一’), 
 );*/
 /** 
  * 输出结构 
  * @var array 
  */
 var $tree = array(); 
 /** 
  * 树形递归的深度 
  * @var int 
  */
 var $deep = 1; 
 /** 
  * 生成树形的修饰符号 
  * @var array 
  */
 var $icon = array(‘│’,'├’,'└’); 
 /** 
  * 生成指定id的下级树形结构 
  * @param int $rootid 要获取树形结构的id 
  * @param string $add 递归中使用的前缀 
  * @param bool $parent_end 标识上级分类是否是最后一个 
  */
 function getTree($rootid = 0,$add = ”,$parent_end =true){ 
  $is_top = 1; 
  $child_arr = $this->getChild($rootid); 
  if(is_array($child_arr)){ 
   $cnt = count($child_arr); 
   foreach($child_arr as $key => $child){ 
    $cid = $child\['id'\]; 
    $child_child = $this->getChild($cid); 
    if($this->deep >1){ 
     if($is_top == 1 && $this->deep > 1){ 
      $space = $this->icon\[1\]; 
      if(!$parent_end) 
      $add .=  $this->icon\[0\]; 
      else $add .= ‘  ’; 
     } 
     if($is_top == $cnt){ 
      $space = $this->icon\[2\]; 
      $parent_end = true; 
     }else { 
      $space = $this->icon\[1\]; 
      $parent_end = false; 
     } 
    } 
    $this->tree\[\] = array(‘spacer’=>$add.$k.$space, 
           ‘name’=>$child\['name'\], 
           ‘id’=>$cid 
    ); 
    $is_top++; 
    $this->deep++; 
    if($this->getChild($cid)) 
    $this->getTree($cid,$add,$parent_end); 
    $this->deep–; 
   } 
  } 
  return $this->tree; 
 } 
 /** 
  * 获取下级分类数组 
  * @param int $root 
  */
 function getChild($root = 0){ 
  $a = $child = array(); 
  foreach($this->arr as $id=>$a){ 
   if($a\['parentid'\] == $root){ 
    $child\[$a\['id'\]\] = $a; 
   } 
  } 
  return $child?$child:false; 
 } 
 /** 
  * 设置源数组 
  * @param $arr 
  */
 function setArr($arr = array()){ 
  $this->arr = $arr; 
 } 
}

通过一次查询把结构保存进一个数组,再数组进行递归运算,无疑极大的提高了程序运行效率
使用代码很简单,得到查询结构后setArr,直接调用getTree, 皆可以得到按照程序排序号并带有前缀修饰等信息的数组,到这里通过foreach这个数组就可以得到如下的树状列表了

水果
├香蕉
├苹果
│├红富士
│└海南苹果
└桃子

在网站开发中,遇到的瓶颈往往来自数据库,而不是程序本身,所以,把更多的工作交给你的php代码吧,虽然复杂点,但是这点牺牲是值得的。