项目思路分析:一个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: 返回数组*/function ReadClass($datatable,$startid,$xtype,$returnArr){$db=$datatable;$sid=$startid;$xtype=$xtype;$lu=$returnArr; $sql="select * from `".$db."` where `pid`="".$sid."" order by xid ".$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: 条件列*/function SelectValue($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 "<select name="pid">";echo "<option value="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 "<option value="".$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 "<select name="pid">";echo "<option value="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 "<option value="".$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` SET rank = 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实现无限极分类的方法,希望对大家的学习有所帮助。