我们在构建类似区域这种层级结构的时候,往往是通过无限循环来构造的。坦白讲,我个人并不喜欢这类解决方式。下面介绍一种方式,可以参考。
我们在做数据库设计的时候,除了id,name,parent外,我还新加了一个grade层次等级的字段。最顶层的数据grade是1,次级是2,依次类推。
也就是说,我们添加地区的时候,这个grade是由父级的grade+1而来的,顶级可以理解为0+1,数据是正确的。
有了grade的标示,我们构建树形结构就方便多了。先看我本地的代码和数据:
// 连接数据库
$con = mysql_connect("localhost", "root", "123456");
if(!$con){ die('Could not connect: ' . mysql_error()); }
mysql_select_db("test", $con);
// 查询所有区域, 注意我们优先使用等级排序,这个很重要
$result = mysql_query("SELECT * FROM region ORDER BY grade asc, id asc");
$region_list = array();
while($row = mysql_fetch_array($result))
{
$temp = array();
$temp['id'] = $row['id'];
$temp['name'] = $row['name'];
$temp['parent'] = $row['parent'];
$temp['grade'] = $row['grade'];
$region_list[] = $temp;
}
mysql_close($con);
// 打印数据
echo '<pre>';
print_r($region_list);
echo '</pre>';
输出结果如下:
Array( [id] => 1, [name] => 新华区, [parent] => 0, [grade] => 1 )
Array( [id] => 2, [name] => 长安区, [parent] => 0, [grade] => 1 )
Array( [id] => 3, [name] => 裕华区, [parent] => 0, [grade] => 1 )
Array( [id] => 4, [name] => 高新区, [parent] => 0, [grade] => 1 )
Array( [id] => 5, [name] => 北国商圈, [parent] => 2, [grade] => 2 )
Array( [id] => 6, [name] => 东尚商圈, [parent] => 2, [grade] => 2 )
Array( [id] => 7, [name] => 博物馆商圈, [parent] => 2, [grade] => 2 )
Array( [id] => 8, [name] => 万达商圈, [parent] => 4, [grade] => 2 )
Array( [id] => 9, [name] => 卓达商圈, [parent] => 4, [grade] => 2 )
Array( [id] => 10, [name] => 范华小区, [parent] => 6, [grade] => 3 )
Array( [id] => 11, [name] => 棉二生活区, [parent] => 6, [grade] => 3 )
Array( [id] => 12, [name] => 市委宿舍, [parent] => 6, [grade] => 3 )
这是一个一维的平面结构,基本看不出上下级关系,关系型数据库存储就是这个样子!
得到这个一维数组后,我的处理逻辑就是将下级数据挂载到上级数据child中,一层一层的挂载,直至最顶级。
// 根据区域等级划分数组, 当然可以从读数据库的时候直接构建此数组
// 注意,我们使用区域ID作为数组下标,进行快速访问
// $grade 是按照1,2,3,4,5顺序的, 由上面SQL查询排序决定
$grade_list = array();
foreach($region_list as $value)
{
$id = $value['id'];
$grade = $value['grade'];
$grade_list[$grade][$id] = $value;
}
这里需要注意的,就是排序问题了,我是希望 $grade_list 里面是按照1,2,3,4,5的顺序组织数据。
接下来就可以按照下层挂载上层的逻辑处理,代码如下:
// 倒叙循环 $grade_list , 将下级区域挂载到上级区域
// $grade 是按照1,2,3,4,5顺序的, 由上面SQL查询排序决定
for($i = count($grade_list); $i > 1; $i--)
{
// 下级区域挂载到上级区域的child中
// $i是下级, $i-1 是上级
foreach($grade_list[$i] as $value)
{
$parent = $value['parent'];
$grade_list[$i-1][$parent]['child'][] = $value;
}
}
循环完毕,上下级关系确定在 $grade_list[1] 里面,也就是最顶层的数据里面。
echo "<pre>";
print_r($grade_list[1]);
echo '</pre>';
输出结果
新华区
长安区
--------北国商圈
--------东尚商圈
--------------------- 范华小区
--------------------- 棉二生活区
--------------------- 市委宿舍
--------博物馆商圈
裕华区
高新区
-------- 万达商圈
--------卓达商圈