我所接触过的无限级分类大致可分为两种,第一种记录路径的,一种是不记录路径的。这两种不同的分类方式在数据库中有着不同的数据存储形式。
第一种:通过父id实现递归
根节点的父id为0,其他子节点的父id为父节点id。然后,通过递归遍历所有节点。
表数据
<?php
//连接数据库
$link = mysqli_connect("localhost","root","root","typepro");
function getAllTypes($space=0, $id=0, $link)
{
$space++;
$rows = mysqli_query($link,"select id,name from type1 where pid=$id");
while ($row = mysqli_fetch_array($rows)) {
echo str_repeat(" ",$space)."|—".$row['name']."<br/>";
getAllTypes($space, $row['id'], $link);
}
}
getAllTypes(0,0,$link);
//关闭连接
mysqli_close($link);
显示效果:

对这段代码进行进一步的优化,譬如:将输出结果保存到数组中、使用Html美化一下输出效果。
<?php
//连接数据库
$link = mysqli_connect("localhost","root","root","typepro");
/**
* 无限分类代码
* @param int 记录递归次数用于显示分类层级
* @param int $id
* @param $result 保存输出结果
* @param $link
*/
function getAllTypes($space=0, $id=0, &$result=array(), $link)
{
$space++;
$rows = mysqli_query($link,"select id,name from type1 where pid=$id");
while ($row = mysqli_fetch_array($rows)) {
$row['echostr'] = str_repeat(" ",$space)."|—".$row['name'];
$result[] = $row;
getAllTypes($space, $row['id'], $result, $link);
}
}
getAllTypes(0,0,$result,$link);
//展示所有分类
echo "<select>";
foreach ($result as $r) {
echo "<option>".$r['echostr']."</option>";
}
echo "</select>";
//关闭连接
mysqli_close($link);
显示效果:
第二种:通过记录路径获取所有子分类
相比于第一种递归方式实现无限分类,记录路径的方式在查询上会更加方便,但是修改分类数据时就会显得略微复杂。
在mysql中建立一个名为path字段,path字段中保存着该节点的所有父节点。通过分割path字段数据可以获取所有节点id。
表数据
<?php
$link = mysqli_connect("localhost","root","root","typepro");
//获取所有分类信息
function gettypes(&$rs,$link)
{
$sql = "select id,name,path,concat(path,',',id) as fullpath from type2 order by fullpath asc ";
$result = mysqli_query($link,$sql);
while($row = mysqli_fetch_array($result)){
$len = count(explode(',',trim($row['fullpath'])));
$row['typestr'] = str_repeat(' ', $len).'|—'.$row['name'];
$rs[] = $row;
}
}
gettypes($rs, $link);
foreach($rs as $r){
echo $r['typestr']."<br/>";
}
//关闭mysql连接
mysqli_close($link);
显示效果: