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:
//#########无限循环公共方法
/**
* @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:
var take_str = '#take';
$(take_str).treetable({ expandable: true});
css:
*{
text-align: left;
margin: 0 auto;
}
.center,.center *{
text-align: center;
}
.width-30{
30%;float: left;
}
.width-70{
70%;float: left;;
}
.width-50{
50%;float: left;
}
.width-100{
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: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: .25rem;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s 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: 1rem;
line-height: 1.5;
white-space: nowrap;
vertical-align: middle;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
._rem{
display: inline-block;
font-weight: 400;
white-space: nowrap;
vertical-align: middle;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: .25rem;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
.form_group{
padding: 10px;
100%;
height: auto;
clear: both;
float: left;
}
.form_group *{
padding: 0 auto;
}
.form_group .form-control {
display: block;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: .25rem;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.heightA,.heightA *{
height: auto;
}
.clear{
clear: both;
}
.error-b{
border: 1px solid #FF0000 !important;
}
.bgr60{
background-color: #320000 !important;
}
template:
<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:
<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
}
]
