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', ) )