PHP 實現無限分類

最近打算作一個blog,一般每篇文章都有屬於本身的分類。下面就記錄下我在寫blog時實現無限分類的過程。php框架用的是laravel,根據註釋也能輕鬆改爲你習慣的框架。php

數據表設計

CREATE TABLE `article_category` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `pid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父id',
  `name` char(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分類名',
  `statu` enum('y','n') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'y' COMMENT '是否顯示',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `remark` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `article_category_pid_index` (`pid`)
) ENGINE=MyISAM AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

程序設計

添加分類

public function addClassify(Request $request)
{
    // laravel 框架自帶的驗證機制
    $this->validate(
        $request,
        [
            'name' => 'required|unique:article_category',
            'remark' => 'max:100',
            'pid' => 'required|numeric'
        ],
        [
            'name.required' => '請填寫分類名!',
            'name.unique' => '改分類名已存在',
            'remark.max' => '分類簡介不能超過100個字符',
            'pid.numeric' => '分類id必須爲數字'
        ]
    );
    // 獲取分類名
    $this->_category->name = $request->input('name');
    // 獲取分類父id,默認是0,爲一級分類
    $this->_category->pid = $request->input('pid',0);
    // 分類簡介
    $this->_category->remark = $request->input('remark');
    // 寫入數據庫
    $result = $this->_category->save();
    // 返回結果
    $result = $result ? '操做成功' : '操做失敗';
    return back()->with('act_msg',$result);
}

獲取分類列表

/**
 * 加載視圖
 * @return [type] [description]
 */
public function classify()
{    
    // 從數據庫獲取全部分類記錄
    $node = $this->_category->orderBy('id','asc')->get();
    // 將分類以及子分類整理排序
    $node = $this->_treeNode($node->toArray(),0);
    // 加載視圖及分配數據
    return view('admin.classify',['list'=>$node]);
}

/**
 * 整理排序全部分類
 * @param  array   $data       從數據庫獲取的分類
 * @param  integer $parentId 父id,默認一級分類
 * @return array 
 */
private function _treeNode($data,$parentId = 0)
{
    // 用於保存整理好的分類節點
    $node = [];
    // 循環全部分類
    foreach ($data as $key => $value) {
        // 若是當前分類的父id等於要尋找的父id則寫入$node數組,並尋找當前分類id下的全部子分類
        if($parentId == $value ['pid']) {
            $node [$key] = $value;
            $node [$key] ['childer'] = $this->_treeNode($data,$value ['id']);
        }
    }
    return $node;
}

方法classify是用於從數據庫獲取全部分類以及顯示模板。方法_treeNode是一個遞歸函數。將從數據庫獲取的全部分類整理排序。排序好的效果以下圖:html

圖片描述

渲染視圖

<table class="table table-border table-bordered table-bg table-hover table-sort">
            <thead>
                <tr class="text-c">
                    <th width="25"><input type="checkbox" name="" value=""></th>
                    <th width="80">ID</th>
                    <!-- <th>標題</th> -->
                    <th width="120">分類名</th>
                    <th width="80">簡介</th>
                    <!-- <th width="80">來源</th> -->
                    <th width="120">更新時間</th>
                    <th width="60">發佈狀態</th>
                    <th width="120">操做</th>
                </tr>
            </thead>
            <tbody>
            <!--遍歷數據-->
            @foreach($list as $val)
                <tr class="text-c">
                    <td><input type="checkbox" value="" name=""></td>
                    <td>{{$val ['id']}}</td>
                    <td class="text-l">
                        <u title="查看">{{$val ['name']}}</u>
                    </td>
                    <td>{{$val ['remark']}}</td>
                    <td>{{$val ['updated_at']}}</td>
                    <td>
                        @if($val ['statu'] == 'y')
                            <span class="label label-success radius">啓用</span> 
                        @else 
                            <span class="label label-danger radius">禁用</span> 
                        @endif
                    </td>
                    <td class="f-14 td-manage">
                        <a><i class="Hui-iconfont">&#xe6de;</i></a>
                         <a><i class="Hui-iconfont">&#xe6df;</i></a>
                          <a title="刪除"><i class="Hui-iconfont">&#xe6e2;</i></a>
                    </td>
                </tr>
                <!--判斷該分類下是否有子分類-->
                @if(!empty($val ['childer']))
                    {{get_childer_node($val ['childer'])}}
                @endif
            @endforeach
            </tbody>
        </table>

渲染視圖時須要判斷該分類下是否有子分類,若是隻作到三級分類,此時只須要再來個二層循環就ok了。這邊我自定義了一個遞歸函數get_childer_node 用於獲取該分類下的子分類。具體實現以下:node

/**
 * 獲取子節點
 * @param  array  $data [description]
 * @return [type]       [description]
 */
function get_childer_node($data = [])
{
    // 記錄該分類的深度
    static $callNum = 1;
    if(empty($data)) 
        return;
    foreach ($data as $key => $val) {
        if($val ['statu'] == 'y')
            $isShow = '<span class="label label-success radius">啓用</span>';
        else
            $isShow = '<span class="label label-danger radius">禁用</span>';
        echo <<<HTML
                <tr class="text-c">
                <td><input type="checkbox" value="" name=""></td>
                <td>{$val ['id']}</td>
                <td class="text-l">|----{$val ['name']}</span></td>
                <td>{$val ['remark']}</td>
                <td>{$val ['updated_at']}</td>
                <td>$isShow</td>
                <td>
                    <a><i class="Hui-iconfont">&#xe6df;</i></a>
                    <a><i class="Hui-iconfont">&#xe6e2;</i></a>
                </td>
            </tr>
    HTML;
        // 若是該分類的依舊有子分類則再次遍歷輸出 
        if(!empty($val ['childer'])) {
            $callNum ++;
            get_childer_node($val ['childer']);
        }
        // 重置分類層級
        $callNum = 1;
    }
}

最終效果

圖片描述

相關文章
相關標籤/搜索