最近打算做一个blog,通常每篇文章都有属于自己的分类。下面就记录下我在写blog时实现无限分类的过程。php框架用的是laravel,根据注释也能轻松改成你习惯的框架。
数据表设计
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
是一个递归函数。将从数据库获取的所有分类整理排序。排序好的效果如下图:
渲染视图
<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
用于获取该分类下的子分类。具体实现如下:
/**
* 获取子节点
* @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;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。