轻松递归无限分类
protected $idName = 'stc_id';
protected $parentName = 'stc_parent_id';
/**
* 获取子集并递归
* @param $data
* @param $id
* @param array $new_arr
* @return array
*/
private function whileWhere($data,$id,&$new_arr=[])
{
$select_frist = $this->get_child_array($data,$id);
foreach ($select_frist as $Keies => $value) {
$new_obj = $this->get_child_array($data,$value[$this->idName]);
if(count($new_obj)){
$new_value = [];
$new_arr[] = array_merge($value,["node"=> $this->whileWhere($data,$value[$this->idName],$new_value[])]);
continue;
}
$new_arr[] = $value;
}
return $new_arr;
}
/**
* 子类集
* @param $data
* @param $id
* @return array
*/
protected function get_child_array($data,$id)
{
$new_data = [];
foreach ($data as $k=>$v){
if($v[$this->parentName] === $id){
$new_data[] = array_merge($data[$k],$this->is_child($data,$v[$this->idName]));
}
}
return $new_data;
}
/**
* 查询是否有子集
* @param $data
* @param $id
* @return array
*/
protected function is_child($data,$id)
{
foreach ($data as $k=>$v){
if($id === $v[$this->parentName] ){
return ['child'=>true];
}
}
return ['child'=>false];
}
请不要使用数据库查询操作递归,用语言本身才不会被外部约束!
以上使用id 父id 两个字段完成递归,举一反三哟!
结果:
array(3) { [0] => array(7) { ["stc_id"] => int(1) ["stc_name"] => string(6) "灏忓崕" ["stc_parent_id"] => int(0) ["stc_state"] => int(1) ["stc_sort"] => int(1) ["child"] => bool(true) ["node"] => array(1) { [0] => array(7) { ["stc_id"] => int(3) ["stc_name"] => string(6) "灏忓洓" ["stc_parent_id"] => int(1) ["stc_state"] => int(0) ["stc_sort"] => int(0) ["child"] => bool(true) ["node"] => array(1) { [0] => array(6) { ["stc_id"] => int(4) ["stc_name"] => string(6) "灏忎簲" ["stc_parent_id"] => int(3) ["stc_state"] => int(0) ["stc_sort"] => int(0) ["child"] => bool(false) } } } } } [1] => array(6) { ["stc_id"] => int(5) ["stc_name"] => string(6) "灏忓叚" ["stc_parent_id"] => int(0) ["stc_state"] => int(0) ["stc_sort"] => int(0) ["child"] => bool(false) } [2] => array(6) { ["stc_id"] => int(2) ["stc_name"] => string(6) "灏忕櫧" ["stc_parent_id"] => int(0) ["stc_state"] => int(0) ["stc_sort"] => int(0) ["child"] => bool(false) } }
分类菜单数据渲染案例:
php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | //#########无限循环公共方法 /** * @param $data * @param $id * @param array $new_arr * @return array */ function whileWhere($data,$id,$idName,$parentName,&$new_arr=[],$mode='mode:node') { $select_frist = get_child_array($data,$id,$idName,$parentName,$mode); foreach ($select_frist as $Keies => $value) { $new_obj = get_child_array($data,$value[$idName],$idName,$parentName,$mode); if(count($new_obj)){ $new_value = []; if($mode === 'mode:node'){ $new_arr[] = array_merge($value,["node"=>whileWhere($data,$value[$idName],$idName,$parentName,$new_value,$mode)]); }elseif($mode === 'mode:array_push'){ $nodes = whileWhere($data,$value[$idName],$idName,$parentName,$new_value,$mode); array_push($new_arr,$value); if(count($nodes)) foreach ($nodes as $key =>$vlaue){ array_push($new_arr,$vlaue); } } continue; } $new_arr[] = $value; }; return $new_arr; } /** * @param $data * @param $id * @return array */ function get_child_array($data,$id,$idName,$parentName,$mode) { $new_data = []; foreach ($data as $k=>$v){ if($v[$parentName] === $id){ $new_data[] = array_merge($data[$k],is_child($data,$v[$idName],$parentName)); } } return $new_data; } /** * @param $data * @param $id * @return array */ function is_child($data,$id,$parentName) { foreach ($data as $k=>$v){ if($id === $v[$parentName] ){ return ['child'=>true]; } } return ['child'=>false]; } //#控制器 public function index(MicroGoodsStyleCategory $category) { $data = $category->field('style_name,style_id,style_parent')->order('sort asc,style_id asc')->select()->toArray(); $arr_calss = []; $classed = whileWhere($data,0,'style_id','style_parent',$arr_calss,'mode:array_push'); return json(msg_array(1,'ok',$classed)); } |
js:
1 2 | var take_str = '#take' ; $(take_str).treetable({ expandable: true }); |
css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | *{ text-align : left ; margin : 0 auto ; } . center ,. center *{ text-align : center ; } .width -30 { width : 30% ; float : left ; } .width -70 { width : 70% ; float : left ;; } .width -50 { width : 50% ; float : left ; } .width -100 { width : 100% ; float : left ; } .padding_ 15 ,.padding_ 15 *{ padding : 0 15px ; -moz-box-sizing: border-box; /*Firefox3.5+*/ -webkit-box-sizing: border-box; /*Safari3.2+*/ -o-box-sizing: border-box; /*Opera9.6*/ -ms-box-sizing: border-box; /*IE8*/ box-sizing: border-box; /*W3C标准(IE9+,Safari5.1+,Chrome10.0+,Opera10.6+都符合box-sizing的w3c标准语法)*/ } .floatL{ float : left ; } .btn{ display : inline- block ; font-weight : 400 ; text-align : center ; white-space : nowrap ; vertical-align : middle ; -webkit-user-select: none ; -moz-user-select: none ; -ms-user-select: none ; user-select: none ; border : 1px solid transparent ; padding : . 375 rem . 75 rem; font-size : 1 rem; line-height : 1.5 ; border-radius: . 25 rem; transition: color . 15 s ease-in-out,background-color . 15 s ease-in-out,border-color . 15 s ease-in-out,box-shadow . 15 s ease-in-out; } .btn-primary { color : #fff ; background-color : #007bff ; border-color : #007bff ; } .selected a{ color : #fff ; } .style_management table tr { height : 30px ; font-size : 1 rem; line-height : 1.5 ; white-space : nowrap ; vertical-align : middle ; transition: color . 15 s ease-in-out,background-color . 15 s ease-in-out,border-color . 15 s ease-in-out,box-shadow . 15 s ease-in-out; } ._rem{ display : inline- block ; font-weight : 400 ; white-space : nowrap ; vertical-align : middle ; padding : . 375 rem . 75 rem; font-size : 1 rem; line-height : 1.5 ; border-radius: . 25 rem; transition: color . 15 s ease-in-out,background-color . 15 s ease-in-out,border-color . 15 s ease-in-out,box-shadow . 15 s ease-in-out; } .form_group{ padding : 10px ; width : 100% ; height : auto ; clear : both ; float : left ; } .form_group *{ padding : 0 auto ; } .form_group .form-control { display : block ; padding : . 375 rem . 75 rem; font-size : 1 rem; line-height : 1.5 ; color : #495057 ; background-color : #fff ; background- clip : padding-box; border : 1px solid #ced4da ; border-radius: . 25 rem; transition: border-color . 15 s ease-in-out, box-shadow . 15 s ease-in-out; } .heightA,.heightA *{ height : auto ; } .clear{ clear : both ; } .error-b{ border : 1px solid #FF0000 !important ; } .bgr 60 { background-color : #320000 !important ; } |
template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <thead> <tr> <td>自定义分类</td> </tr> </thead> <tbody> {{each datas}} {{set v = $value}} <tr data-tt-id= "{{v.style_id}}" data-tt-parent-id= "{{v.style_parent}}" > <td class= "width-70 floatL " >{{v.style_name}}</td> <td class= "width-30 floatL center" > <a href= "#" class= "width-50 edit" data-id= "{{v.style_id}}" > 编辑</a> <a href= "#" class= "width-50 del" data-id= "{{v.style_id}}" >删除</a> </td> </tr> {{/each}} </tbody> |
Html:
1 2 3 4 5 6 7 8 | < link rel="stylesheet" href="//cdn.bootcss.com/jquery-treetable/3.2.0/css/jquery.treetable.css"> < link rel="stylesheet" href="//cdn.bootcss.com/jquery-treetable/3.2.0/css/jquery.treetable.theme.default.css"> < link rel="stylesheet" href="//cdn.bootcss.com/jquery-modal/0.9.1/jquery.modal.css"> < table id="take"> < script type="text/javascript" src="//cdn.bootcss.com/jquery-treetable/3.2.0/jquery.treetable.min.js"></ script > |
效果:(jquery-treetable 在数据显示上,其实没有特别的能帮到帮忙。它一定需要你去在返回数据时,按层级的排列数据,否则你会觉得很烦恼。数据参考格式:
[
{
"style_name": "欧美风",
"style_id": 6,
"style_parent": 0,
"child": true
},
{
"style_name": "美式",
"style_id": 10,
"style_parent": 6,
"child": true
},
{
"style_name": "田园风",
"style_id": 11,
"style_parent": 10,
"child": false
},
{
"style_name": "中式风",
"style_id": 8,
"style_parent": 0,
"child": false
},
{
"style_name": "美国风",
"style_id": 9,
"style_parent": 0,
"child": false
}
]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南