PHP整理CMS无限层级目录(毗邻目录模式)

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


你可能感兴趣的:(PHP,毗邻目录模式)