最近打算作一個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"></i></a> <a><i class="Hui-iconfont"></i></a> <a title="刪除"><i class="Hui-iconfont"></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"></i></a> <a><i class="Hui-iconfont"></i></a> </td> </tr> HTML; // 若是該分類的依舊有子分類則再次遍歷輸出 if(!empty($val ['childer'])) { $callNum ++; get_childer_node($val ['childer']); } // 重置分類層級 $callNum = 1; } }