php+mysql实现无限级分类
项目思路分析:一个PHP项目要用到分类,但不确定分几级,所以就想做成无限级分类。
一开始想是按以前一样,数据库建4个值,如下:
id:自增 | pid:父类ID | xid:排序ID | classname:分类名称
后来想到这种在读取数据时和修改时比较不方便,而且在产品读取时尤其不便,于时改成了以下的方案:
在Mysql的表中新增了一个字段,现数据库如下:
表名w_faqclass: id:自增 | pid:父类ID | xid:排序ID | classname:分类名称 | rank: 等级
定义:
一级分类,pid为0,rank为"/"
二级分类,pid为一级分类的id,rank为"/一级分类的id/"
三级分类,pid为二级分类的id,rank为"/一级分类的id/二级分类的id/"
依此类推...
1.基础函数
/* 利于递归返回已经进行了排序的无限级分类的数组 不想用递归的话也可以用like来获取后再进行排序,我比较懒,就不写那种获取方式了,其实用like更好,推荐用那种方式 $datatable:数据表名 $startid:开始父类ID $wheretColumns:父类列名 $xColumns:排序列名 $xtype:排序方式 $returnArr:返回数组 */ functionReadClass($datatable,$startid,$xtype,$returnArr){ $db=$datatable; $sid=$startid; $xtype=$xtype; $lu=$returnArr; $sql="select*from`".$db."`where`pid`='".$sid."'orderbyxid".$xtype.";"; $cresult=mysql_query($sql); if(mysql_num_rows($cresult)>0){ while($rs=mysql_fetch_array($cresult)){ $lunum=count($lu); $lu[$lunum]['id']=$rs['id']; $lu[$lunum]['pid']=$rs['pid']; $lu[$lunum]['rank']=$rs['rank']; $lu[$lunum]['classname']=$rs['classname']; $lu[$lunum]['xid']=$rs['xid']; $lu=ReadClass($db,$rs['id'],$xtype,$lu); } } return$lu; } /* 查询某表中的某个值,只会返回一个值 $datatable:数据表名 $wherevalue:条件值 $selectColumns:查询列名 $whereColumns:条件列 */ functionSelectValue($datatable,$wherevalue,$selectColumns,$whereColumns){ $sql="select`".$selectColumns."`from`".$datatable."`where`".$whereColumns."`='".$wherevalue."';"; $result=mysql_query($sql); while($rs=mysql_fetch_array($result)){ return$rs[$selectColumns]; } }
2.增加分类(直接做到了select中用于选择)
<?php $classArr=ReadClass('w_faqclass','0','asc',array()); $canum=count($classArr); echo"<selectname='pid'>"; echo"<optionvalue='0'>主分类</option>"; for($i=0;$i<$canum;$i++){ $rankArr=split("/",$classArr[$i]['rank']); $ranknum=count($rankArr); $t=""; for($j=1;$j<$ranknum;$j++){//用于格式化显示子类 $t.="├┄┄"; } echo"<optionvalue='".$classArr[$i]['id']."'>".$t.$classArr[$i]['classname']."</option>"; } echo"</select>" ?> //保存时的操作,需要判断是否为主分类,当为主类时,rank值设为/ //查询父类的rank值,用父类的rank加上父类的id值 if($pid!=0){ $pidrank=SelectValue('w_faqclass',$pid,'rank','id'); $rank=$pidrank.$pid."/"; }else{ $rank="/"; }
3.修改分类
<?php /* 注意,因为是修改,在此页面加载时已将当前分类的所有值读出来了,对应是:$pid,$rank */ $classArr=ReadClass('w_faqclass','0','asc',array()); $canum=count($classArr); echo"<selectname='pid'>"; echo"<optionvalue='0'>主分类</option>"; for($i=0;$i<$canum;$i++){ //因为是修改,所以当前分类不能选择自身或自身以下的分类,多加个rank值的优势啊,哈哈,以前做单pid值的时候这里还得用次递归查询 while($ids==$classArr[$i]['id']||strstr($classArr[$i]['rank'],$rank.$ids."/")){ $i++; } $rankArr=split("/",$classArr[$i]['rank']); $ranknum=count($rankArr); $t=""; for($j=1;$j<$ranknum;$j++){ $t.="├┄┄"; } if($pid==$classArr[$i]['id']){ $selected="selected"; }else{ $selected=""; } echo"<optionvalue='".$classArr[$i]['id']."'".$selected.">".$t.$classArr[$i]['classname']."</option>"; } echo"</select>" ?> //保存时的操作 //要做到改动时该分类的所有子分类rank值都需要变动,选取得原来子分类通用到的rank值,也就是该分类的rank值加上它的ID值 //利于mysql的REPLACE语句进行替换 if($pid!=0){ $pidrank=SelectValue('w_faqclass',$pid,'rank','id'); $rank=$pidrank.$pid."/"; }else{ $rank="/"; } $orank=SelectValue('w_faqclass',$ids,'rank','id').$ids."/"; $nrank=$rank.$ids."/"; mysql_query("UPDATE`w_faqclass`SETrank=REPLACE(rank,'".$orank."','".$nrank."');"); mysql_query("UPDATE`w_faqclass`SET`classname`='".$classname."',`xid`='".$xid."',`pid`='".$pid."',`rank`='".$rank."'where`id`='".$ids."';");
4.删除和查询就简单了,这个就不赘述了,提到一点,记得在删除前确认下该类下面是否存在子类就可以了。
$zid=SelectValue('w_faqclass',$ids,'id','pid'); if($zid>0){ ... }
以上就是php+mysql实现无限极分类的方法,希望对大家的学习有所帮助。