本文實例講述了PHP帶節(jié)點操作的無限分類實現方法。分享給大家供大家參考,具體如下:
包含(移動多個節(jié)點;移動單個節(jié)點;刪除多個節(jié)點;刪除單個節(jié)點;新增節(jié)點),另附數據庫表結構
一、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 */ /** *用于移動一個節(jié)點(包括子節(jié)點) *@param array $pdata = array('id'=>主鍵,'root'=>名稱) 二選一 父節(jié)點(為空時插入最大的父節(jié)點) *@param array $ndata = array('id'=>主鍵,'root'=>名稱) 二選一 下一個兄弟節(jié)點(沒有兄弟的時候就不用) *@param array $cdata = array('id'=>主鍵,'root'=>名稱) 二選一 當前待移動的節(jié)點 */ 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 ); //獲取當前移動節(jié)點的所有節(jié)點 delete_tree_all( $cdata ,1); //邏輯刪除當前移動節(jié)點的所有節(jié)點 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); } } } /** *用于移動一個節(jié)點(不包括子節(jié)點) *@param array $pdata = array('id'=>主鍵,'root'=>名稱) 二選一 父節(jié)點(為空時插入最大的父節(jié)點) *@param array $ndata = array('id'=>主鍵,'root'=>名稱) 二選一 下一個兄弟節(jié)點(沒有兄弟的時候就不用) *@param array $cdata = array('id'=>主鍵,'root'=>名稱) 二選一 當前待移動的節(jié)點 */ 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); } /** *用于插入一個節(jié)點 *@param array $pdata = array('id'=>主鍵,'root'=>名稱) 二選一 父節(jié)點(為空時插入最大的父節(jié)點) *@param array $ndata = array('id'=>主鍵,'root'=>名稱) 二選一 下一個兄弟節(jié)點(沒有兄弟的時候就不用) *@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' ]; //有父無兄(最小的子節(jié)點,父節(jié)點的最后一個兒子) 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 ); //新節(jié)點 $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 ); //新節(jié)點 $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 ); //新節(jié)點 $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 } } /** *用于刪除一個節(jié)點(包括子節(jié)點) *@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 ); } /** *用于刪除一個節(jié)點(不包括子節(jié)點) *@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 ); } /** *用于獲取所有的節(jié)點 *@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' ]) { // 檢查我們是否應該將節(jié)點移出堆棧 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) { // 檢查我們是否應該將節(jié)點移出堆棧 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程序設計有所幫助。