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

左右值实现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 && !$croot) return; 
  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 && !$croot) return; 
  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(!$name) return; 
  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.          
  90.         mysql_query($sql1); 
  91.         mysql_query($sql2); 
  92.         mysql_query($sql); //last add new data 
  93.     } 
  94.     //有父有兄 
  95.     if(($pid || $proot) && ($nid || $nroot)) { 
  96.         $sql    =  $nid ? "SELECT lft, rgt FROM tree WHERE id = '{$nid}';" : "SELECT lft, rgt FROM tree WHERE name = '{$nroot}';"; 
  97.         $result = mysql_query($sql); 
  98.         $row    = mysql_fetch_assoc($result); 
  99.         unset($sql); 
  100.         //新节点 
  101.         $lft  = $row['lft']; 
  102.         $rgt  = $lft+1; 
  103.         if(!$update) { 
  104.             $sql  = "insert into tree values (null,'{$name}',$lft,$rgt,0);"; 
  105.             $sql1 = "update tree set rgt = rgt+2 where rgt >= {$row['lft']};"; 
  106.             $sql2 = "update tree set lft = lft+2 where lft >= {$row['lft']};"; 
  107.         } else { 
  108.             $sql  = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';"; 
  109.             $sql1 = "update tree set rgt = rgt+2 where status = 0 and rgt >= {$row['lft']};"; 
  110.             $sql2 = "update tree set lft = lft+2 where status = 0 and lft >= {$row['lft']};"; 
  111.         } 
  112.         mysql_query($sql1); 
  113.         mysql_query($sql2); 
  114.         mysql_query($sql); //last add new data 
  115.     } 
  116.     //无父无兄(大佬) 
  117.     if(!($pid || $proot) && !($nid || $nroot)) { 
  118.         $sql    =  "SELECT max(`rgt`) as rgt FROM tree;"; 
  119.         $result = mysql_query($sql); 
  120.         $row    = mysql_fetch_assoc($result); 
  121.         unset($sql); 
  122.         //新节点 
  123.         $lft  = 1; 
  124.         $rgt  = $row['rgt']+2; 
  125.         if(!$update) { 
  126.             $sql  = "insert into tree values (null,'{$name}',$lft,$rgt,0);"; 
  127.             $sql1 = "update tree set rgt = rgt+1"; 
  128.             $sql2 = "update tree set lft = lft+1"; 
  129.         } else { 
  130.             $sql  = "update tree set lft=$lft,rgt=$rgt,status=0 where name ='{$name}';"; 
  131.             $sql1 = "update tree set rgt = rgt+1 where status = 0"; 
  132.             $sql2 = "update tree set lft = lft+1 where status = 0"; 
  133.         } 
  134.          
  135.         mysql_query($sql1); 
  136.         mysql_query($sql2); 
  137.         mysql_query($sql); //last add new data 
  138.     } 
  139.     
  140. } 
  141. /** 
  142.  *用于删除一个节点(包括子节点) 
  143.  *@param array $data = array('id'=>主键,'root'=>名称) 二选一 
  144.  *@param int $update 默认为空,为1时逻辑删除 
  145.  */ 
  146. function delete_tree_all($data,$update='') { 
  147.     $id   = $data['id'] ? intval($data['id']) : ''; 
  148.     $root = $data['root']; 
  149.     if(!$id && !$root) return; 
  150.     $sql    =  $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';"; 
  151.     $result = mysql_query($sql); 
  152.     $row    = mysql_fetch_assoc($result); 
  153.     unset($sql); 
  154.     $middle = $row['rgt']-$row['lft']+1; 
  155.     if(!$update) { 
  156.         $sql    = "delete from tree where lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."'"; 
  157.         $sql1   = "update tree set rgt = rgt-{$middle} where rgt > {$row['rgt']}"; 
  158.         $sql2   = "update tree set lft = lft-{$middle} where lft > {$row['rgt']}"; 
  159.     } else { 
  160.         $sql    = "update tree set status = 1 where lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."'"; 
  161.         $sql1   = "update tree set rgt = rgt-{$middle} where status=0 and rgt > {$row['rgt']}"; 
  162.         $sql2   = "update tree set lft = lft-{$middle} where status=0 and lft > {$row['rgt']}"; 
  163.     }  
  164.      
  165.     mysql_query($sql); 
  166.     mysql_query($sql1); 
  167.     mysql_query($sql2); 
  168. } 
  169. /** 
  170.  *用于删除一个节点(不包括子节点) 
  171.  *@param array $data = array('id'=>主键,'root'=>名称) 二选一 
  172.  *@param int $update 默认为空,为1时逻辑删除 
  173.  */ 
  174. function delete_tree_item($data,$update='') { 
  175.     $id   = $data['id'] ? intval($data['id']) : ''; 
  176.     $root = $data['root']; 
  177.     if(!$id && !$root) return; 
  178.     $sql    =  $id ? "SELECT id,lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT id,lft, rgt FROM tree WHERE name = '{$root}';"; 
  179.     $result = mysql_query($sql); 
  180.     $row    = mysql_fetch_assoc($result); 
  181.     unset($sql); 
  182.     if(!$update) { 
  183.         $sql  = "delete from tree where id = {$row['id']};"; 
  184.         $sql1 = "update tree set rgt = rgt-1,lft = lft -1 where lft > {$row['lft']} and rgt < {$row['rgt']}"; 
  185.         $sql2 = "update tree set lft = lft-2 where lft > {$row['rgt']}"; 
  186.         $sql3 = "update tree set rgt = rgt-2 where rgt > {$row['rgt']}"; 
  187.     } else { 
  188.         $sql  = "update tree set status = 1 where id = {$row['id']};"; 
  189.         $sql1 = "update tree set rgt = rgt-1,lft = lft -1 where status = 0 and lft > {$row['lft']} and rgt < {$row['rgt']}"; 
  190.         $sql2 = "update tree set lft = lft-2 where status = 0 and lft > {$row['rgt']}"; 
  191.         $sql3 = "update tree set rgt = rgt-2 where status = 0 and rgt > {$row['rgt']}"; 
  192.     } 
  193.      
  194.     mysql_query($sql); 
  195.     mysql_query($sql1); 
  196.     //can do or not do just right,but not do load empty 2 number in middle 
  197.     mysql_query($sql2); 
  198.     mysql_query($sql3); 
  199. } 
  200. /** 
  201.  *用于获取所有的节点 
  202.  *@param array $data = array('id'=>主键,'root'=>名称) 二选一 
  203.  */ 
  204. function get_tree_all($data) { 
  205.     $id   = $data['id'] ? intval($data['id']) : ''; 
  206.     $root = $data['root']; 
  207.     if(!$id && !$root) return; 
  208.     $sql    =  $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';"; 
  209.     $result = mysql_query($sql); 
  210.     $row    = mysql_fetch_assoc($result); 
  211.     $adata  = array(); //所有数据 
  212.     $right  = array(); //计数 
  213.     $prev   = array(); 
  214.     $result = mysql_query("SELECT id,name, lft, rgt FROM tree WHERE lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."' ORDER BY lft ASC ;"); 
  215.     while ($row = mysql_fetch_assoc($result)) { 
  216.         if (count($right) > 0) { 
  217.             while ($right[count($right) - 1] < $row['rgt']) { // 检查我们是否应该将节点移出堆栈 
  218.                 array_pop($right); 
  219.                 array_pop($prev); 
  220.             } 
  221.         } 
  222.         $parent  = $prev ? end($prev) : ''; 
  223.         $adata[] = array('id'=>$row['id'],'name'=>$row['name'],'level'=>count($right),'parent'=>$parent); 
  224.         $right[] = $row['rgt']; 
  225.         $prev[]  = $row['name']; 
  226.     } 
  227.     return $adata; 
  228. } 
  229. /** 
  230.  *用于展示分类 
  231.  *@param array $data = array('id'=>主键,'root'=>名称) 二选一 
  232.  */ 
  233. function display_tree($data) { 
  234.     $id   = $data['id'] ? intval($data['id']) : ''; 
  235.     $root = $data['root']; 
  236.     if(!$id && !$root) return; 
  237.     $sql    =  $id ? "SELECT lft, rgt FROM tree WHERE id = '{$id}';" : "SELECT lft, rgt FROM tree WHERE name = '{$root}';"; 
  238.     $result = mysql_query($sql); 
  239.     $row    = mysql_fetch_assoc($result); 
  240.     $right  = array(); 
  241.     $result = mysql_query("SELECT name, lft, rgt FROM tree WHERE lft BETWEEN '" . $row['lft'] . "' AND '" . $row['rgt'] ."' ORDER BY lft ASC ;"); 
  242.     while ($row = mysql_fetch_assoc($result)) { 
  243.         if (count($right) > 0) { // 检查我们是否应该将节点移出堆栈 
  244.             while ($right[count($right) - 1] < $row['rgt']) { 
  245.                 array_pop($right); 
  246.             } 
  247.         } 
  248.         echo str_repeat('  ',count($right)) . $row['name'] . "\n"; 
  249.         $right[] = $row['rgt']; 
  250.     } 
  251. } 
  252. mysql_connect('localhost','root','') or die('connect error'); 
  253. mysql_select_db('test') or die('database error'); 
  254. mysql_query('set names utf8'); 
  255. display_tree(array('root'=>'Food')); 
  256. //display_tree(array('root'=>'bigboss')); 
  257. //move_tree_all($pdata=array('root'=>'Fruit'),$ndata=array('root'=>'Red'),$cdata=array('root'=>'Meat')); 
  258. //move_tree_all('','',$cdata=array('root'=>'Meat')); 
  259. //move_tree_item('','',array('root'=>'Red')); 
  260. //move_tree_item(array('root'=>'Red'),array('root'=>'Cherry'),array('root'=>'Fruit')); //phpfensi.com 
  261. //delete_tree_all(array('root'=>'Yellow')); 
  262. //delete_tree_all(array('root'=>'Meat')); 
  263. //delete_tree_item(array('root'=>'Meat')); 
  264. //insert_tree('','','bigboss'); 
  265. //insert_tree(array('root'=>'Red'),'','dalao'); 
  266. //insert_tree(array('root'=>'Red'),array('root'=>'Cherry'),'baddalao'); 
  267. //insert_tree(array('root'=>'Fruit'),array('root'=>'Red'),'Redbother'); 
  268. display_tree(array('root'=>'Food')); 

Tags: PHP无限分类 PHP左右值

分享到: