A-A+

左右值实现PHP无限分类例子

2019年02月16日 我爱编程 暂无评论

无限分类在栏目分类中我们经常会用到了,今天来看一个使用左右值实现PHP无限分类例子了,希望这个例子可以对各位带来帮助.

一、db sql语句

  1. //db used for php无限分类
  2. create table tree(
  3.     id int(10) not null primary key auto_increment,
  4.     name varchar(255) not null,
  5.     lft int(10) not null default 0,
  6.     rgt int(10) not null default 0,
  7.     status int(1) not null default 0,
  8.     index lft (`lft`),
  9.     index rgt (`rgt`),
  10.     index status(`status`)
  11. )charset utf8;
  12. insert into tree value (null,'Food',1,18,0);
  13. insert into tree value (null,'Fruit',2,11,0);
  14. insert into tree value (null,'Red',3,6,0);
  15. insert into tree value (null,'Cherry',4,5,0);
  16. insert into tree value (null,'Yellow',7,10,0);
  17. insert into tree value (null,'Banana',8,9,0);
  18. insert into tree value (null,'Meat',12,17,0);
  19. insert into tree value (null,'Beef',13,14,0);
  20. insert into tree value (null,'Pork',15,16,0);

二、php文件

  1. <?php
  2. error_reporting(0);
  3. /*
  4.                          1 Food 18
  5.             +------------------------------+
  6.         2 Fruit 11                     12 Meat 17
  7.     +-------------+                 +------------+
  8. 3 Red 6      7 Yellow 10       13 Beef 14   15 Pork 16
  9. 4 Cherry 5    8 Banana 9
  10. descendants = (right – left - 1) / 2
  11. */
  12. /**
  13.  *用于移动一个节点(包括子节点)
  14.  *@param array $pdata = array('id'=>主键,'root'=>名称) 二选一 父节点(为空时插入最大的父节点)
  15.  *@param array $ndata = array('id'=>主键,'root'=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用)
  16.  *@param array $cdata = array('id'=>主键,'root'=>名称) 二选一 当前待移动的节点
  17.  */
  18. function move_tree_all($pdata=array(),$ndata=array(),$cdata=array()) {
  19.     $cid   = $cdata['id'] ? intval($cdata['id']) : '';
  20.     $croot = $cdata['root'];
  21.     if(!$cid && !$crootreturn;
  22.     //需自加判断
  23.     //1、cdata不能为顶级
  24.     //2、cdata不能比$pdata等级高
  25.     $adata = get_tree_all($cdata); //获取当前移动节点的所有节点
  26.     delete_tree_all($cdata,1); //逻辑删除当前移动节点的所有节点
  27.     foreach($adata as $k => $val) {
  28.         if($k != 0) {
  29.             $pdata = array('root'=>$val['parent']);
  30.             insert_tree($pdata,'',$val['name'],1);
  31.         } else { //first
  32.             insert_tree($pdata,$ndata,$val['name'],1);
  33.         }
  34.     }
  35. }
  36. /**
  37.  *用于移动一个节点(不包括子节点)
  38.  *@param array $pdata = array('id'=>主键,'root'=>名称) 二选一 父节点(为空时插入最大的父节点)
  39.  *@param array $ndata = array('id'=>主键,'root'=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用)
  40.  *@param array $cdata = array('id'=>主键,'root'=>名称) 二选一 当前待移动的节点
  41.  */
  42. function move_tree_item($pdata=array(),$ndata=array(),$cdata=array()) {
  43.     $cid   = $cdata['id'] ? intval($cdata['id']) : '';
  44.     $croot = $cdata['root'];
  45.     if(!$cid && !$crootreturn;
  46.     //需自加判断
  47.     //1、cdata不能为顶级
  48.     if(!$croot) {
  49.         $sql = "SELECT name from tree where id = $cid";
  50.         $result = mysql_query($sql);
  51.         $row = mysql_fetch_assoc($result);
  52.         $croot = $row['name'];
  53.         unset($sql);
  54.     }
  55.     delete_tree_item($cdata,1);
  56.     insert_tree($pdata,$ndata,$croot,1);
  57. }
  58. /**
  59.  *用于插入一个节点
  60.  *@param array $pdata = array('id'=>主键,'root'=>名称) 二选一 父节点(为空时插入最大的父节点)
  61.  *@param array $ndata = array('id'=>主键,'root'=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用)
  62.  *@param string $name string 新插入的名称
  63.  *@param int $update 默认为空,为1时更新插入
  64.  */
  65. function insert_tree($pdata=array(),$ndata=array(),$name,$update='') {
  66.     if(!$namereturn;
  67.     $pid   = $pdata['id'] ? intval($pdata['id']) : '';
  68.     $proot = $pdata['root'];
  69.     $nid   = $ndata['id'] ? intval($ndata['id']) : '';
  70.     $nroot = $ndata['root'];
  71.     //有父无兄(最小的子节点,父节点的最后一个儿子)
  72.     if(($pid || $proot) && !($nid || $nroot)) {
  73.         $sql    =  $pid ? "SELECT lft, rgt FROM tree WHERE id = '{$pid}';" : "SELECT lft, rgt FROM tree WHERE name = '{$proot}';";
  74.         $result = mysql_query($sql);
  75.         $row    = mysql_fetch_assoc($result);
  76.         unset($sql);
  77.         //新节点
  78.         $lft  = $row['rgt'];
  79.         $rgt  = $lft+1;
  80.         if(!$update) {
  81.             $sql  = "insert into tree values (null,'{$name}',$lft,$rgt,0);";
  82.             $sql1 = "update tree set rgt = rgt+2 where rgt >= {$row['rgt']}";
  83.             $sql2 = "update tree set lft = lft+2 where lft >= {$row['rgt']}";
  84.         } else {
  85.             $sql  = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';";
  86.             $sql1 = "update tree set rgt = rgt+2 where status =0 and rgt >= {$row['rgt']}";
  87.             $sql2 = "update tree set lft = lft+2 where status =0 and lft >= {$row['rgt']}";
  88.         }
  89.         mysql_query($sql1);
  90.         mysql_query($sql2);
  91.         mysql_query($sql); //last add new data
  92.     }
  93.     //有父有兄
  94.     if(($pid || $proot) && ($nid || $nroot)) {
  95.         $sql    =  $nid ? "SELECT lft, rgt FROM tree WHERE id = '{$nid}';" : "SELECT lft, rgt FROM tree WHERE name = '{$nroot}';";
  96.         $result = mysql_query($sql);
  97.         $row    = mysql_fetch_assoc($result);
  98.         unset($sql);
  99.         //新节点
  100.         $lft  = $row['lft'];
  101.         $rgt  = $lft+1;
  102.         if(!$update) {
  103.             $sql  = "insert into tree values (null,'{$name}',$lft,$rgt,0);";
  104.             $sql1 = "update tree set rgt = rgt+2 where rgt >= {$row['lft']};";
  105.             $sql2 = "update tree set lft = lft+2 where lft >= {$row['lft']};";
  106.         } else {
  107.             $sql  = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';";
  108.             $sql1 = "update tree set rgt = rgt+2 where status = 0 and rgt >= {$row['lft']};";
  109.             $sql2 = "update tree set lft = lft+2 where status = 0 and lft >= {$row['lft']};";
  110.         }
  111.         mysql_query($sql1);
  112.         mysql_query($sql2);
  113.         mysql_query($sql); //last add new data
  114.     }
  115.     //无父无兄(大佬)
  116.     if(!($pid || $proot) && !($nid || $nroot)) {
  117.         $sql    =  "SELECT max(`rgt`) as rgt FROM tree;";
  118.         $result = mysql_query($sql);
  119.         $row    = mysql_fetch_assoc($result);
  120.         unset($sql);
  121.         //新节点
  122.         $lft  = 1;
  123.         $rgt  = $row['rgt']+2;
  124.         if(!$update) {
  125.             $sql  = "insert into tree values (null,'{$name}',$lft,$rgt,0);";
  126.             $sql1 = "update tree set rgt = rgt+1";
  127.             $sql2 = "update tree set lft = lft+1";
  128.         } else {
  129.             $sql  = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';";
  130.             $sql1 = "update tree set rgt = rgt+1 where status = 0";
  131.             $sql2 = "update tree set lft = lft+1 where status = 0";
  132.         }
  133.         mysql_query($sql1);
  134.         mysql_query($sql2);
  135.         mysql_query($sql); //last add new data
  136.     }
  137. }
  138. /**
  139.  *用于删除一个节点(包括子节点)
  140.  *@param array $data = array('id'=>主键,'root'=>名称) 二选一
  141.  *@param int $update 默认为空,为1时逻辑删除
  142.  */
  143. function delete_tree_all($data,$update='') {
  144.     $id   = $data['id'] ? intval($data['id']) : '';
  145.     $root = $data['root'];
  146.     if(!$id && !$rootreturn;
  147.     $sql    =  $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';";
  148.     $result = mysql_query($sql);
  149.     $row    = mysql_fetch_assoc($result);
  150.     unset($sql);
  151.     $middle = $row['rgt']-$row['lft']+1;
  152.     if(!$update) {
  153.         $sql    = "delete from tree where lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."'";
  154.         $sql1   = "update tree set rgt = rgt-{$middle} where rgt > {$row['rgt']}";
  155.         $sql2   = "update tree set lft = lft-{$middle} where lft > {$row['rgt']}";
  156.     } else {
  157.         $sql    = "update tree set status = 1 where lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."'";
  158.         $sql1   = "update tree set rgt = rgt-{$middle} where status=0 and rgt > {$row['rgt']}";
  159.         $sql2   = "update tree set lft = lft-{$middle} where status=0 and lft > {$row['rgt']}";
  160.     }
  161.     mysql_query($sql);
  162.     mysql_query($sql1);
  163.     mysql_query($sql2);
  164. }
  165. /**
  166.  *用于删除一个节点(不包括子节点)
  167.  *@param array $data = array('id'=>主键,'root'=>名称) 二选一
  168.  *@param int $update 默认为空,为1时逻辑删除
  169.  */
  170. function delete_tree_item($data,$update='') {
  171.     $id   = $data['id'] ? intval($data['id']) : '';
  172.     $root = $data['root'];
  173.     if(!$id && !$rootreturn;
  174.     $sql    =  $id ? "SELECT id,lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT id,lft, rgt FROM tree WHERE name = '{$root}';";
  175.     $result = mysql_query($sql);
  176.     $row    = mysql_fetch_assoc($result);
  177.     unset($sql);
  178.     if(!$update) {
  179.         $sql  = "delete from tree where id = {$row['id']};";
  180.         $sql1 = "update tree set rgt = rgt-1,lft = lft -1 where lft > {$row['lft']} and rgt < {$row['rgt']}";
  181.         $sql2 = "update tree set lft = lft-2 where lft > {$row['rgt']}";
  182.         $sql3 = "update tree set rgt = rgt-2 where rgt > {$row['rgt']}";
  183.     } else {
  184.         $sql  = "update tree set status = 1 where id = {$row['id']};";
  185.         $sql1 = "update tree set rgt = rgt-1,lft = lft -1 where status = 0 and lft > {$row['lft']} and rgt < {$row['rgt']}";
  186.         $sql2 = "update tree set lft = lft-2 where status = 0 and lft > {$row['rgt']}";
  187.         $sql3 = "update tree set rgt = rgt-2 where status = 0 and rgt > {$row['rgt']}";
  188.     }
  189.     mysql_query($sql);
  190.     mysql_query($sql1);
  191.     //can do or not do just right,but not do load empty 2 number in middle
  192.     mysql_query($sql2);
  193.     mysql_query($sql3);
  194. }
  195. /**
  196.  *用于获取所有的节点
  197.  *@param array $data = array('id'=>主键,'root'=>名称) 二选一
  198.  */
  199. function get_tree_all($data) {
  200.     $id   = $data['id'] ? intval($data['id']) : '';
  201.     $root = $data['root'];
  202.     if(!$id && !$rootreturn;
  203.     $sql    =  $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';";
  204.     $result = mysql_query($sql);
  205.     $row    = mysql_fetch_assoc($result);
  206.     $adata  = array(); //所有数据
  207.     $right  = array(); //计数
  208.     $prev   = array();
  209.     $result = mysql_query("SELECT id,name, lft, rgt FROM tree WHERE lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."' ORDER BY lft ASC ;");
  210.     while ($row = mysql_fetch_assoc($result)) {
  211.         if (count($right) > 0) {
  212.             while ($right[count($right) - 1] < $row['rgt']) { // 检查我们是否应该将节点移出堆栈
  213.                 array_pop($right);
  214.                 array_pop($prev);
  215.             }
  216.         }
  217.         $parent  = $prev ? end($prev) : '';
  218.         $adata[] = array('id'=>$row['id'],'name'=>$row['name'],'level'=>count($right),'parent'=>$parent);
  219.         $right[] = $row['rgt'];
  220.         $prev[]  = $row['name'];
  221.     }
  222.     return $adata;
  223. }
  224. /**
  225.  *用于展示分类
  226.  *@param array $data = array('id'=>主键,'root'=>名称) 二选一
  227.  */
  228. function display_tree($data) {
  229.     $id   = $data['id'] ? intval($data['id']) : '';
  230.     $root = $data['root'];
  231.     if(!$id && !$rootreturn;
  232.     $sql    =  $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';";
  233.     $result = mysql_query($sql);
  234.     $row    = mysql_fetch_assoc($result);
  235.     $right  = array();
  236.     $result = mysql_query("SELECT name, lft, rgt FROM tree WHERE lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."' ORDER BY lft ASC ;");
  237.     while ($row = mysql_fetch_assoc($result)) {
  238.         if (count($right) > 0) { // 检查我们是否应该将节点移出堆栈
  239.             while ($right[count($right) - 1] < $row['rgt']) {
  240.                 array_pop($right);
  241.             }
  242.         }
  243.         echo str_repeat('  ',count($right)) . $row['name'] . "\n";
  244.         $right[] = $row['rgt'];
  245.     }
  246. }
  247. mysql_connect('localhost','root',''or die('connect error');
  248. mysql_select_db('test'or die('database error');
  249. mysql_query('set names utf8');
  250. display_tree(array('root'=>'Food'));
  251. //display_tree(array('root'=>'bigboss'));
  252. //move_tree_all($pdata=array('root'=>'Fruit'),$ndata=array('root'=>'Red'),$cdata=array('root'=>'Meat'));
  253. //move_tree_all('','',$cdata=array('root'=>'Meat'));
  254. //move_tree_item('','',array('root'=>'Red'));
  255. //move_tree_item(array('root'=>'Red'),array('root'=>'Cherry'),array('root'=>'Fruit'));com
  256. //delete_tree_all(array('root'=>'Yellow'));
  257. //delete_tree_all(array('root'=>'Meat'));
  258. //delete_tree_item(array('root'=>'Meat'));
  259. //insert_tree('','','bigboss');
  260. //insert_tree(array('root'=>'Red'),'','dalao');
  261. //insert_tree(array('root'=>'Red'),array('root'=>'Cherry'),'baddalao');
  262. //insert_tree(array('root'=>'Fruit'),array('root'=>'Red'),'Redbother');
  263. display_tree(array('root'=>'Food'));
标签:

给我留言

Copyright © 四季博客 保留所有权利.   Theme  Ality

用户登录