PHP整理CMS無限層級目錄(毗鄰目錄模式)

CMS中的分類每每是能夠無限劃分子目錄的,存儲數據的過程比較容易實現,可是取目錄層級的方式卻比較難搞。php

經常使用的目錄劃分模式有毗鄰目錄模式和預排序遍歷樹(左右值無限分類法)。這裏只討論前一種模式的目錄獲取。sql


正常狀況下,數據庫是這樣設計的(模擬一些數據):數據庫

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以前直接打印結果,能夠獲得一個這樣的數組:code

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',
  )
)
相關文章
相關標籤/搜索