PHP带节点操作的无限分类实现方法详解

2025-05-29 0 91

本文实例讲述了PHP带节点操作的无限分类实现方法。分享给大家供大家参考,具体如下:

包含(移动多个节点;移动单个节点;删除多个节点;删除单个节点;新增节点),另附数据库表结构

一、db sql语句

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20
//db used for php无限分类

create table tree(

id int(10) not null primary key auto_increment,

name varchar(255) not null,

lft int(10) not null default 0,

rgt int(10) not null default 0,

status int(1) not null default 0,

index lft (`lft`),

index rgt (`rgt`),

index status(`status`)

)charset utf8;

insert into tree value (null,'Food',1,18,0);

insert into tree value (null,'Fruit',2,11,0);

insert into tree value (null,'Red',3,6,0);

insert into tree value (null,'Cherry',4,5,0);

insert into tree value (null,'Yellow',7,10,0);

insert into tree value (null,'Banana',8,9,0);

insert into tree value (null,'Meat',12,17,0);

insert into tree value (null,'Beef',13,14,0);

insert into tree value (null,'Pork',15,16,0);

二、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

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

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263
<?php

error_reporting(0);

/*

1 Food 18

+------------------------------+

2 Fruit 11 12 Meat 17

+-------------+ +------------+

3 Red 6 7 Yellow 10 13 Beef 14 15 Pork 16

4 Cherry 5 8 Banana 9

descendants = (right – left - 1) / 2

*/

/**

*用于移动一个节点(包括子节点)

*@param array $pdata = array('id'=>主键,'root'=>名称) 二选一 父节点(为空时插入最大的父节点)

*@param array $ndata = array('id'=>主键,'root'=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用)

*@param array $cdata = array('id'=>主键,'root'=>名称) 二选一 当前待移动的节点

*/

function move_tree_all($pdata=array(),$ndata=array(),$cdata=array()) {

$cid = $cdata['id'] ? intval($cdata['id']) : '';

$croot = $cdata['root'];

if(!$cid && !$croot) return;

//需自加判断

//1、cdata不能为顶级

//2、cdata不能比$pdata等级高

$adata = get_tree_all($cdata); //获取当前移动节点的所有节点

delete_tree_all($cdata,1); //逻辑删除当前移动节点的所有节点

foreach($adata as $k => $val) {

if($k != 0) {

$pdata = array('root'=>$val['parent']);

insert_tree($pdata,'',$val['name'],1);

} else { //first

insert_tree($pdata,$ndata,$val['name'],1);

}

}

}

/**

*用于移动一个节点(不包括子节点)

*@param array $pdata = array('id'=>主键,'root'=>名称) 二选一 父节点(为空时插入最大的父节点)

*@param array $ndata = array('id'=>主键,'root'=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用)

*@param array $cdata = array('id'=>主键,'root'=>名称) 二选一 当前待移动的节点

*/

function move_tree_item($pdata=array(),$ndata=array(),$cdata=array()) {

$cid = $cdata['id'] ? intval($cdata['id']) : '';

$croot = $cdata['root'];

if(!$cid && !$croot) return;

//需自加判断

//1、cdata不能为顶级

if(!$croot) {

$sql = "SELECT name from tree where id = $cid";

$result = mysql_query($sql);

$row = mysql_fetch_assoc($result);

$croot = $row['name'];

unset($sql);

}

delete_tree_item($cdata,1);

insert_tree($pdata,$ndata,$croot,1);

}

/**

*用于插入一个节点

*@param array $pdata = array('id'=>主键,'root'=>名称) 二选一 父节点(为空时插入最大的父节点)

*@param array $ndata = array('id'=>主键,'root'=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用)

*@param string $name string 新插入的名称

*@param int $update 默认为空,为1时更新插入

*/

function insert_tree($pdata=array(),$ndata=array(),$name,$update='') {

if(!$name) return;

$pid = $pdata['id'] ? intval($pdata['id']) : '';

$proot = $pdata['root'];

$nid = $ndata['id'] ? intval($ndata['id']) : '';

$nroot = $ndata['root'];

//有父无兄(最小的子节点,父节点的最后一个儿子)

if(($pid || $proot) && !($nid || $nroot)) {

$sql = $pid ? "SELECT lft, rgt FROM tree WHERE id = '{$pid}';" : "SELECT lft, rgt FROM tree WHERE name = '{$proot}';";

$result = mysql_query($sql);

$row = mysql_fetch_assoc($result);

unset($sql);

//新节点

$lft = $row['rgt'];

$rgt = $lft+1;

if(!$update) {

$sql = "insert into tree values (null,'{$name}',$lft,$rgt,0);";

$sql1 = "update tree set rgt = rgt+2 where rgt >= {$row['rgt']}";

$sql2 = "update tree set lft = lft+2 where lft >= {$row['rgt']}";

} else {

$sql = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';";

$sql1 = "update tree set rgt = rgt+2 where status =0 and rgt >= {$row['rgt']}";

$sql2 = "update tree set lft = lft+2 where status =0 and lft >= {$row['rgt']}";

}

mysql_query($sql1);

mysql_query($sql2);

mysql_query($sql); //last add new data

}

//有父有兄

if(($pid || $proot) && ($nid || $nroot)) {

$sql = $nid ? "SELECT lft, rgt FROM tree WHERE id = '{$nid}';" : "SELECT lft, rgt FROM tree WHERE name = '{$nroot}';";

$result = mysql_query($sql);

$row = mysql_fetch_assoc($result);

unset($sql);

//新节点

$lft = $row['lft'];

$rgt = $lft+1;

if(!$update) {

$sql = "insert into tree values (null,'{$name}',$lft,$rgt,0);";

$sql1 = "update tree set rgt = rgt+2 where rgt >= {$row['lft']};";

$sql2 = "update tree set lft = lft+2 where lft >= {$row['lft']};";

} else {

$sql = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';";

$sql1 = "update tree set rgt = rgt+2 where status = 0 and rgt >= {$row['lft']};";

$sql2 = "update tree set lft = lft+2 where status = 0 and lft >= {$row['lft']};";

}

mysql_query($sql1);

mysql_query($sql2);

mysql_query($sql); //last add new data

}

//无父无兄(大佬)

if(!($pid || $proot) && !($nid || $nroot)) {

$sql = "SELECT max(`rgt`) as rgt FROM tree;";

$result = mysql_query($sql);

$row = mysql_fetch_assoc($result);

unset($sql);

//新节点

$lft = 1;

$rgt = $row['rgt']+2;

if(!$update) {

$sql = "insert into tree values (null,'{$name}',$lft,$rgt,0);";

$sql1 = "update tree set rgt = rgt+1";

$sql2 = "update tree set lft = lft+1";

} else {

$sql = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';";

$sql1 = "update tree set rgt = rgt+1 where status = 0";

$sql2 = "update tree set lft = lft+1 where status = 0";

}

mysql_query($sql1);

mysql_query($sql2);

mysql_query($sql); //last add new data

}

}

/**

*用于删除一个节点(包括子节点)

*@param array $data = array('id'=>主键,'root'=>名称) 二选一

*@param int $update 默认为空,为1时逻辑删除

*/

function delete_tree_all($data,$update='') {

$id = $data['id'] ? intval($data['id']) : '';

$root = $data['root'];

if(!$id && !$root) return;

$sql = $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';";

$result = mysql_query($sql);

$row = mysql_fetch_assoc($result);

unset($sql);

$middle = $row['rgt']-$row['lft']+1;

if(!$update) {

$sql = "delete from tree where lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."'";

$sql1 = "update tree set rgt = rgt-{$middle} where rgt > {$row['rgt']}";

$sql2 = "update tree set lft = lft-{$middle} where lft > {$row['rgt']}";

} else {

$sql = "update tree set status = 1 where lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."'";

$sql1 = "update tree set rgt = rgt-{$middle} where status=0 and rgt > {$row['rgt']}";

$sql2 = "update tree set lft = lft-{$middle} where status=0 and lft > {$row['rgt']}";

}

mysql_query($sql);

mysql_query($sql1);

mysql_query($sql2);

}

/**

*用于删除一个节点(不包括子节点)

*@param array $data = array('id'=>主键,'root'=>名称) 二选一

*@param int $update 默认为空,为1时逻辑删除

*/

function delete_tree_item($data,$update='') {

$id = $data['id'] ? intval($data['id']) : '';

$root = $data['root'];

if(!$id && !$root) return;

$sql = $id ? "SELECT id,lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT id,lft, rgt FROM tree WHERE name = '{$root}';";

$result = mysql_query($sql);

$row = mysql_fetch_assoc($result);

unset($sql);

if(!$update) {

$sql = "delete from tree where id = {$row['id']};";

$sql1 = "update tree set rgt = rgt-1,lft = lft -1 where lft > {$row['lft']} and rgt < {$row['rgt']}";

$sql2 = "update tree set lft = lft-2 where lft > {$row['rgt']}";

$sql3 = "update tree set rgt = rgt-2 where rgt > {$row['rgt']}";

} else {

$sql = "update tree set status = 1 where id = {$row['id']};";

$sql1 = "update tree set rgt = rgt-1,lft = lft -1 where status = 0 and lft > {$row['lft']} and rgt < {$row['rgt']}";

$sql2 = "update tree set lft = lft-2 where status = 0 and lft > {$row['rgt']}";

$sql3 = "update tree set rgt = rgt-2 where status = 0 and rgt > {$row['rgt']}";

}

mysql_query($sql);

mysql_query($sql1);

//can do or not do just right,but not do load empty 2 number in middle

mysql_query($sql2);

mysql_query($sql3);

}

/**

*用于获取所有的节点

*@param array $data = array('id'=>主键,'root'=>名称) 二选一

*/

function get_tree_all($data) {

$id = $data['id'] ? intval($data['id']) : '';

$root = $data['root'];

if(!$id && !$root) return;

$sql = $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';";

$result = mysql_query($sql);

$row = mysql_fetch_assoc($result);

$adata = array(); //所有数据

$right = array(); //计数

$prev = array();

$result = mysql_query("SELECT id,name, lft, rgt FROM tree WHERE lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."' ORDER BY lft ASC ;");

while ($row = mysql_fetch_assoc($result)) {

if (count($right) > 0) {

while ($right[count($right) - 1] < $row['rgt']) { // 检查我们是否应该将节点移出堆栈

array_pop($right);

array_pop($prev);

}

}

$parent = $prev ? end($prev) : '';

$adata[] = array('id'=>$row['id'],'name'=>$row['name'],'level'=>count($right),'parent'=>$parent);

$right[] = $row['rgt'];

$prev[] = $row['name'];

}

return $adata;

}

/**

*用于展示分类

*@param array $data = array('id'=>主键,'root'=>名称) 二选一

*/

function display_tree($data) {

$id = $data['id'] ? intval($data['id']) : '';

$root = $data['root'];

if(!$id && !$root) return;

$sql = $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';";

$result = mysql_query($sql);

$row = mysql_fetch_assoc($result);

$right = array();

$result = mysql_query("SELECT name, lft, rgt FROM tree WHERE lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."' ORDER BY lft ASC ;");

while ($row = mysql_fetch_assoc($result)) {

if (count($right) > 0) { // 检查我们是否应该将节点移出堆栈

while ($right[count($right) - 1] < $row['rgt']) {

array_pop($right);

}

}

echo str_repeat(' ',count($right)) . $row['name'] . "\\n";

$right[] = $row['rgt'];

}

}

mysql_connect('localhost','root','') or die('connect error');

mysql_select_db('test') or die('database error');

mysql_query('set names utf8');

display_tree(array('root'=>'Food'));

//display_tree(array('root'=>'bigboss'));

//move_tree_all($pdata=array('root'=>'Fruit'),$ndata=array('root'=>'Red'),$cdata=array('root'=>'Meat'));

//move_tree_all('','',$cdata=array('root'=>'Meat'));

//move_tree_item('','',array('root'=>'Red'));

//move_tree_item(array('root'=>'Red'),array('root'=>'Cherry'),array('root'=>'Fruit'));

//delete_tree_all(array('root'=>'Yellow'));

//delete_tree_all(array('root'=>'Meat'));

//delete_tree_item(array('root'=>'Meat'));

//insert_tree('','','bigboss');

//insert_tree(array('root'=>'Red'),'','dalao');

//insert_tree(array('root'=>'Red'),array('root'=>'Cherry'),'baddalao');

//insert_tree(array('root'=>'Fruit'),array('root'=>'Red'),'Redbother');

display_tree(array('root'=>'Food'));

希望本文所述对大家PHP程序设计有所帮助。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 PHP带节点操作的无限分类实现方法详解 https://www.kuaiidc.com/95925.html

相关文章

发表评论
暂无评论