无限极分类树
# 无限级分类树类
class Tree
{
/**
* @var object 对象实例
*/
protected static $instance;
/**
* @var array 存放无限级分类的结果
*/
public static $treeList = [];
protected static $config = [
"id" => "id", // id
"pid" => "pid", // pid
"title" => "title", // 标题名称
"child" => "child", // 子元素键名
"html" => "┝ ", // 层级标记
"step" => 4, // 层级步进数量
];
/**
* 构造函数
* Tree constructor.
* @param array $config
*/
public function __construct($config = [])
{
self::$config = array_merge(self::$config, $config);
}
/**
* 参数配置
* @param array $config
* @return Tree|object
*/
public static function config($config = [])
{
if (!empty($config)) {
$config = array_merge(self::$config, $config);
}
if (is_null(self::$instance)) {
self::$instance = new static($config);
}
return self::$instance;
}
/**
* @param $data
* @param int $pid
* @return array
*/
public static function create($data, $pid = 0)
{
foreach ($data as $key => $value) {
if ($value['pid'] == $pid) {
self::$treeList[] = $value;
unset($data[$key]);
self::create($data, $value['id']);
}
}
return self::$treeList;
}
/**
* 将数据集格式化成层次结构
* @param array $lists
* @param int $pid
* @param int $max_level
* @param int $curr_level
* @return array
*/
public static function toLayer($lists = [], $pid = 0, $max_level = 0, $curr_level = 0)
{
$trees = [];
$lists = array_values($lists);
foreach ($lists as $key => $value) {
if ($value[self::$config['pid']] == $pid) {
if ($max_level > 0 && $curr_level == $max_level) {
return $trees;
}
unset($lists[$key]);
$child = self::toLayer($lists, $value[self::$config['id']], $max_level, $curr_level + 1);
if (!empty($child)) {
$value[self::$config['child']] = $child;
}
$trees[] = $value;
}
}
return $trees;
}
/**
* 将数据集格式化成列表结构
* @param array $lists
* @param int $pid
* @param int $level
* @return array
*/
public static function toList($lists = [], $pid = 0, $level = 0)
{
if (is_array($lists)) {
$trees = [];
foreach ($lists as $key => $value) {
if ($value[self::$config['pid']] == $pid) {
$title_prefix = str_repeat(
"-",
$level * self::$config['step']
).self::$config['html'];
$value['level'] = $level + 1;
$value['title_prefix'] = $level == 0 ? '' : $title_prefix;
$value['title_display'] = $level == 0 ? $value[self::$config['title']] : $title_prefix.$value[self::$config['title']];
$trees[] = $value;
unset($lists[$key]);
$trees = array_merge($trees, self::toList($lists, $value[self::$config['id']], $level + 1));
}
}
return $trees;
} else {
foreach ($lists as $key => $value) {
if ($value[self::$config['pid']] == $pid && is_object($value)) {
$title_prefix = str_repeat(
" ",
$level * self::$config['step']
).self::$config['html'];
$value['level'] = $level + 1;
$value['title_prefix'] = $level == 0 ? '' : $title_prefix;
$value['title_display'] = $level == 0 ? $value[self::$config['title']] : $title_prefix.$value[self::$config['title']];
$lists->offsetUnset($key);
$lists[] = $value;
self::toList($lists, $value[self::$config['id']], $level + 1);
}
}
return $lists;
}
}
/**
* 根据子节点返回所有父节点
* @param array $lists
* @param string $id
* @return array
*/
public static function getParents($lists = [], $id = '')
{
$trees = [];
foreach ($lists as $value) {
if ($value[self::$config['id']] == $id) {
$trees[] = $value;
$trees = array_merge(self::getParents($lists, $value[self::$config['pid']]), $trees);
}
}
return $trees;
}
/**
* 获取所有子节点id
* @param array $lists
* @param string $pid
* @return array
*/
public static function getChildsId($lists = [], $pid = '')
{
$result = [];
foreach ($lists as $value) {
if ($value[self::$config['pid']] == $pid) {
$result[] = $value[self::$config['id']];
$result = array_merge($result, self::getChildsId($lists, $value[self::$config['id']]));
}
}
return $result;
}
/**
* 获取所有子节点
* @param array $lists
* @param string $pid
* @return array
*/
public static function getChilds($lists = [], $pid = '')
{
$result = [];
foreach ($lists as $value) {
if ($value[self::$config['pid']] == $pid) {
$result[] = $value;
$result = array_merge($result, self::getChilds($lists, $value[self::$config['id']]));
}
}
return $result;
}
/**
* 根据子分类获取顶级分类
* @param $id
* @return mixed
*/
public static function getNavPid($id)
{
$catId = Category::get($id);
if ($catId['pid'] != 0) {
return self::getNavPid($catId['pid']);
}
return $catId['id'];
}
}
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
- Index控制器调用分类
public function index()
{
try {
$list = $this->categoryBus->getList();
$list = Tree::toList($list);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
return view('category/index', compact('list'));
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 生成的数据结构
对于这样的结构,相信大家也会进行正确的调用了,只不过我这里将
Tree
类中的分隔符缓存了-
,没有改用空格,使用空格会代来一些意想不到的错误,如果使用页面解析的函数进行输出,就会产生错误。
- 模板页面的显示内容
<table class="table table-bordered table-responsive table-hover">
<thead>
<tr>
<th>#ID</th>
<th>分类标题</th>
<th>排序</th>
<th>状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{volist name="list" id="vo"}
<tr>
<td>{$vo.id}</td>
<td>{$vo.title_display}</td>
<td>{$vo.order}</td>
<td>{$vo.status}</td>
<td>{$vo.create_time}</td>
<td>
<a href="{:url('admin/Category/create', array('pid' => $vo.id))}"
class="btn btn-primary">添加子分类</a>
<a href="{:url('admin/Category/edit', array('id' => $vo.id))}"
class="btn btn-success">编辑</a>
<a data-id="{$vo.id}" onclick="confirm_msg(this, '确定要删除吗')"
class="btn btn-danger">删除</a>
</td>
</tr>
{/volist}
</tbody>
</table>
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
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
# 好处
- 不用费心思去搞
js
去进行树结构解析什么的 - 不用费心思的一遍一遍的循环
tr
,使用另外的那种无限极分类的函数来获取child
子元素数组,再进行循环,这样有多少个就要foreach
多少遍,确实挺繁琐的
编辑 (opens new window)
上次更新: 2021/10/21, 20:43:49