实现无限级分类一般只用一个数据表,通常可通过递归和非递归两种方法来实现。递归方法必须使用递归调用方式才能进行数据遍历,删除等操作,所以需要发送多次查询数据库语句,非常影响执行效率。那么非递归该怎样来实现无限分类呢?简单来说可用一张表四个字段和一条语句来实现。
1、一张表四个字段
1 | DROPTABLEIFEXISTS`wb_columns`; |
2 | CREATETABLE`eway_columns`( |
3 | `colId`smallint(5)unsignedNOTNULLAUTO_INCREMENT, |
4 | `colPid`smallint(5)unsignedNOTNULLDEFAULT'0', |
5 | `colPath`varchar(100)NOTNULLDEFAULT'', |
6 | `colTitle`varchar(100)NOTNULLDEFAULT'', |
9 | )ENGINE=MyISAMCHARSET=utf8; |
2、一条语句
1 | SELECTconcat(colPath,'-',colId)ASbpath,colId,colPid,colPath,colTitle,FROM".C('DB_PREFIX')."columnsORDERBYbpath,colId; |
在上面的一条语句的SQL查询中,使用MYSQL中的concat函数将colPath和colId字段通过字符"-"连接起来,并将该字段设置为bpath别名。然后先通过bpathpb字段进行排序,如果有相同的路径再通过colId字段进行排序,这样就会以分类的各级层次结构将结果返回。
下面是在thinkphp3.1中非递归无限级分类的实现代码
03 | *分类Columns的控制器ColumnsAction.class.php |
05 | classColumnsActionextendsAction{ |
09 | $catarray=$this->Catlist(); |
11 | $this->assign('catarray',$catarray); |
17 | publicfunctioninsert(){ |
18 | $catarray=$this->Catlist(); |
20 | $this->assign('catarray',$catarray); |
28 | if($vo=$D->create()){//因为使用模型类处理,自动完成必须通过create方法才能生效。 |
31 | $this->success("添加成功"); |
37 | $this->error($D->getError()); |
44 | $list=$Columns->query("SELECTconcat(colPath,'-',colId)ASbpath,colId,colPid,colPath,colTitle,FROM".C('DB_PREFIX')."columnsORDERBYbpath,colId"); |
46 | foreach($listas$k=>$v){ |
47 | $list[$k]['count']=count(explode('-',$v['bpath'])); |
48 | $list[$k]['total']=$Module->where('catid='.$v['colId'])->count(); |
51 | for($i=0;$i<$list[$k]['count']*2;$i++){ |
56 | $list[$k]['space']=$str; |
64 | *分类Columns的模型类ColumnsModel.class.php |
65 | *作用:在添加分类或修改分类时自动处理colPath字段并保存到数据库中 |
66 | *callback:回调方法,表示填充的内容是一个当前模型的方法 |
67 | *Model::MODEL_INSERT或者1新增数据时候验证 |
68 | *Model::MODEL_UPDATE或者2编辑数据时候验证 |
69 | *Model::MODEL_BOTH或者3全部情况下验证(默认),这里选择该验证。 |
72 | classColumnsModelextendsModel{ |
73 | protected$_auto=array(//thinkphp的自动填充 |
74 | array('colPath','colPath',3,'callback'), |
79 | $colPid=isset($_POST['colPid'])?(int)$_POST['colPid']:0; |
80 | $colId=$_POST['colId']; |
85 | $fat=$this->where('colId='.$colPid)->find();//查询的是父级ID |
86 | $data=$fat['colPath'].'-'.$fat['colId'];//得到父级的colPath,连上父级ID,返回的是子级的colPath |
需要注意的是,这是使用模型的自动完成功能,所以必须通过create方法才能生效,Create方法创建的数据对象是保存在内存中,并没有实际写入到数据库中,直到使用add方法才真正写入数据库中。