CMS中的分类往往是可以无限划分子目录的,存储数据的过程比较容易实现,但是取目录层级的方式却比较难搞。
常用的目录划分模式有毗邻目录模式和预排序遍历树(左右值无限分类法)。这里只讨论前一种模式的目录获取。
正常情况下,数据库是这样设计的(模拟一些数据):
id title parent
1 新闻 0
2 生活 0
3 旅游 0
4 国内 1
5 国际 1
6 社会 4
7 美食 2
8 景点 3
这里只是模拟一个简单的结构。
下面取出数据后,放在数组里。
$cat = array(
array(
'id' => 1,
'title' => '新闻',
'parent' => 0
),
...
);
这里不再详细的写数组了 以下是处理函数:
/**
* 主要的处理函数,规整目录的层级
*
* @param array
*
* @return array
*/
public function get_categories($cats){
//取所有分类
if (!$cats || empty($cats)) {
return false;
}
//将分类按级别整理成一个数组
$first = array();
$level = array(array(0));
$i = 0;
while (count($cats) > 0) {
foreach ($cats as $k => $v) {
if (in_array($v['parent'], $level[$i])) {
$first[$i][$v['id']] = $v;
$level[$i+1][] = $v['id'];
unset($cats[$k]);
}
}
$i++;
}
//将数组按分类整理归属
$first = array_reverse($first);//将数组顺序翻转
$sorted = array();
$children = array();//定义一个存储子节点的数组
foreach ($first as $key => $val) {
if (!empty($children)) {
foreach ($children as $num => $row) {
$val[$num]['children'] = $row;
}
$children = array();
}
foreach ($val as $num => $row) {
if ($row['parent'] > 0) {
$children[$row['parent']][] = $row;
}
}
$sorted = $val;
}
//数组降维度 名称修饰
return arr_align($sorted);
}
在调用arr_algin之前直接打印结果,可以得到一个这样的数组:
array(
1 =>
array(
'id' => string '1',
'title' => string '新闻',
'parent' => string '0',
'children' =>
array(
0 =>
array(
'id' => string '4',
'title' => string '国内',
'parent' => string '1',
'children' =>
array(
0 => array(
...
)
)
)
...
)
),
2 =>
array(
'id' => string '2',
'title' => string '生活',
'parent' => string '0',
),
3 =>
array(
'id' => string '3',
'title' => string '旅游',
'parent' => string '0',
)
)
通过下面的递归函数将数组转换成一个简单的二位数组,将栏目按照层级展示出来:
/**
* 将多维数组维度降为2,栏目名称按维度标注
*
* @param array,int
*
* @return array
*/
function arr_align($arr,$level=0){
$level++;//这个变量会帮你打印好很有很有层次的'-- '
static $data;//定义一个静态变量用来存储最终结果
foreach ($arr as $val) {
$temp = $val;
$temp['title'] = str_repeat('-- ',$level).$temp['title'];
if (isset($val['children'])) {
unset($temp['children']);
$data[] = $temp;
arr_align($val['children'],$level);//递归调用
}
else{
$data[] = $temp;
}
}
return $data;
}
处理后的结果:
0 =>
array(
'id' => string '1',
'title' => string '-- 新闻',
'parent' => string '0',
),
1 =>
array(
'id' => string '4',
'title' => string '-- -- 国内',
'parent' => string '1',
),
2 =>
array(
'id' => string '6',
'title' => string '-- -- -- 社会',
'parent' => string '4',
),
3 =>
array(
'id' => string '5',
'title' => string '-- -- 国际',
'parent' => string '1',
),
4 =>
array(
'id' => string '2',
'title' => string '-- 生活',
'parent' => string '1',
),
5 =>
array(
'id' => string '7',
'title' => string '-- -- 美食',
'parent' => string '2',
),
6 =>
array(
'id' => string '3',
'title' => string '-- 旅游',
'parent' => string '0',
),
5 =>
array(
'id' => string '8',
'title' => string '-- -- 景点',
'parent' => string '3',
)
)