当前位置:首页 > 综合实例 > 列表

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

发布:smiling 来源: PHP粉丝网  添加日期:2016-08-30 14:53:43 浏览: 评论:0 

无限分类在栏目分类中我们经常会用到了,今天来看一个使用左右值实现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`), --phpfensi.com 
  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.  *@param array $pdata = array('id'=>主键,'root'=>名称) 二选一 父节点(为空时插入最大的父节点) 
  38.  *@param array $ndata = array('id'=>主键,'root'=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用) 
  39.  *@param array $cdata = array('id'=>主键,'root'=>名称) 二选一 当前待移动的节点 
  40.  */ 
  41. function move_tree_item($pdata=array(),$ndata=array(),$cdata=array()) { 
  42.     $cid   = $cdata['id'] ? intval($cdata['id']) : ''
  43.     $croot = $cdata['root']; 
  44.     if(!$cid && !$crootreturn
  45.     //需自加判断 
  46.     //1、cdata不能为顶级 
  47.     if(!$croot) { 
  48.         $sql = "SELECT name from tree where id = $cid"
  49.         $result = mysql_query($sql); 
  50.         $row = mysql_fetch_assoc($result); 
  51.         $croot = $row['name']; 
  52.         unset($sql); 
  53.     } 
  54.     delete_tree_item($cdata,1); 
  55.     insert_tree($pdata,$ndata,$croot,1); 
  56. /** 
  57.  *用于插入一个节点 
  58.  *@param array $pdata = array('id'=>主键,'root'=>名称) 二选一 父节点(为空时插入最大的父节点) 
  59.  *@param array $ndata = array('id'=>主键,'root'=>名称) 二选一 下一个兄弟节点(没有兄弟的时候就不用) 
  60.  *@param string $name string 新插入的名称 
  61.  *@param int $update 默认为空,为1时更新插入 
  62.  */ 
  63. function insert_tree($pdata=array(),$ndata=array(),$name,$update='') { 
  64.     if(!$namereturn
  65.     $pid   = $pdata['id'] ? intval($pdata['id']) : ''
  66.     $proot = $pdata['root']; 
  67.     $nid   = $ndata['id'] ? intval($ndata['id']) : ''
  68.     $nroot = $ndata['root']; 
  69.     //有父无兄(最小的子节点,父节点的最后一个儿子) 
  70.     if(($pid || $proot) && !($nid || $nroot)) { 
  71.         $sql    =  $pid ? "SELECT lft, rgt FROM tree WHERE id = '{$pid}';" : "SELECT lft, rgt FROM tree WHERE name = '{$proot}';"
  72.         $result = mysql_query($sql); 
  73.         $row    = mysql_fetch_assoc($result); 
  74.         unset($sql); 
  75.         //新节点 
  76.         $lft  = $row['rgt']; 
  77.         $rgt  = $lft+1; 
  78.         if(!$update) { 
  79.             $sql  = "insert into tree values (null,'{$name}',$lft,$rgt,0);"
  80.             $sql1 = "update tree set rgt = rgt+2 where rgt >= {$row['rgt']}"
  81.             $sql2 = "update tree set lft = lft+2 where lft >= {$row['rgt']}"
  82.         } else { 
  83.             $sql  = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';"
  84.             $sql1 = "update tree set rgt = rgt+2 where status =0 and rgt >= {$row['rgt']}"
  85.             $sql2 = "update tree set lft = lft+2 where status =0 and lft >= {$row['rgt']}"
  86.         } 
  87.          
  88.         mysql_query($sql1); 
  89.         mysql_query($sql2); 
  90.         mysql_query($sql); //last add new data 
  91.     } 
  92.     //有父有兄 
  93.     if(($pid || $proot) && ($nid || $nroot)) { 
  94.         $sql    =  $nid ? "SELECT lft, rgt FROM tree WHERE id = '{$nid}';" : "SELECT lft, rgt FROM tree WHERE name = '{$nroot}';"
  95.         $result = mysql_query($sql); 
  96.         $row    = mysql_fetch_assoc($result); 
  97.         unset($sql); 
  98.         //新节点 
  99.         $lft  = $row['lft']; 
  100.         $rgt  = $lft+1; 
  101.         if(!$update) { 
  102.             $sql  = "insert into tree values (null,'{$name}',$lft,$rgt,0);"
  103.             $sql1 = "update tree set rgt = rgt+2 where rgt >= {$row['lft']};"
  104.             $sql2 = "update tree set lft = lft+2 where lft >= {$row['lft']};"
  105.         } else { 
  106.             $sql  = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';"
  107.             $sql1 = "update tree set rgt = rgt+2 where status = 0 and rgt >= {$row['lft']};"
  108.             $sql2 = "update tree set lft = lft+2 where status = 0 and lft >= {$row['lft']};"
  109.         } 
  110.         mysql_query($sql1); 
  111.         mysql_query($sql2); 
  112.         mysql_query($sql); //last add new data 
  113.     } 
  114.     //无父无兄(大佬) 
  115.     if(!($pid || $proot) && !($nid || $nroot)) { 
  116.         $sql    =  "SELECT max(`rgt`) as rgt FROM tree;"
  117.         $result = mysql_query($sql); 
  118.         $row    = mysql_fetch_assoc($result); 
  119.         unset($sql); 
  120.         //新节点 
  121.         $lft  = 1; 
  122.         $rgt  = $row['rgt']+2; 
  123.         if(!$update) { 
  124.             $sql  = "insert into tree values (null,'{$name}',$lft,$rgt,0);"
  125.             $sql1 = "update tree set rgt = rgt+1"
  126.             $sql2 = "update tree set lft = lft+1"
  127.         } else { 
  128.             $sql  = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';"
  129.             $sql1 = "update tree set rgt = rgt+1 where status = 0"
  130.             $sql2 = "update tree set lft = lft+1 where status = 0"
  131.         } 
  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.      
  162.     mysql_query($sql); 
  163.     mysql_query($sql1); 
  164.     mysql_query($sql2); 
  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.      
  190.     mysql_query($sql); 
  191.     mysql_query($sql1); 
  192.     //can do or not do just right,but not do load empty 2 number in middle 
  193.     mysql_query($sql2); 
  194.     mysql_query($sql3); 
  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.  *@param array $data = array('id'=>主键,'root'=>名称) 二选一 
  226.  */ 
  227. function display_tree($data) { 
  228.     $id   = $data['id'] ? intval($data['id']) : ''
  229.     $root = $data['root']; 
  230.     if(!$id && !$rootreturn
  231.     $sql    =  $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';"
  232.     $result = mysql_query($sql); 
  233.     $row    = mysql_fetch_assoc($result); 
  234.     $right  = array(); 
  235.     $result = mysql_query("SELECT name, lft, rgt FROM tree WHERE lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."' ORDER BY lft ASC ;"); 
  236.     while ($row = mysql_fetch_assoc($result)) { 
  237.         if (count($right) > 0) { // 检查我们是否应该将节点移出堆栈 
  238.             while ($right[count($right) - 1] < $row['rgt']) { 
  239.                 array_pop($right); 
  240.             } 
  241.         } 
  242.         echo str_repeat('  ',count($right)) . $row['name'] . "\n"
  243.         $right[] = $row['rgt']; 
  244.     } 
  245. mysql_connect('localhost','root',''or die('connect error'); 
  246. mysql_select_db('test'or die('database error'); 
  247. mysql_query('set names utf8'); 
  248. display_tree(array('root'=>'Food')); 
  249. //display_tree(array('root'=>'bigboss')); 
  250. //move_tree_all($pdata=array('root'=>'Fruit'),$ndata=array('root'=>'Red'),$cdata=array('root'=>'Meat')); 
  251. //move_tree_all('','',$cdata=array('root'=>'Meat')); 
  252. //move_tree_item('','',array('root'=>'Red')); 
  253. //move_tree_item(array('root'=>'Red'),array('root'=>'Cherry'),array('root'=>'Fruit')); //phpfensi.com 
  254. //delete_tree_all(array('root'=>'Yellow')); 
  255. //delete_tree_all(array('root'=>'Meat')); 
  256. //delete_tree_item(array('root'=>'Meat')); 
  257. //insert_tree('','','bigboss'); 
  258. //insert_tree(array('root'=>'Red'),'','dalao'); 
  259. //insert_tree(array('root'=>'Red'),array('root'=>'Cherry'),'baddalao'); 
  260. //insert_tree(array('root'=>'Fruit'),array('root'=>'Red'),'Redbother'); 
  261. display_tree(array('root'=>'Food')); 

Tags: PHP无限分类 PHP左右值

分享到: