zoukankan      html  css  js  c++  java
  • 左右值编码,文章类别。无限级分类

    在网上也搜了很多的例子,根据网络上的解释,慢慢摸索,用了将近2周的时间。笨人,没办法。有什么错的 请留言哦。

    在yii php框架下 无限级分类。

    通过网络上的,我们都了解到 实现文章 无限级分类,可以使用左右值编码,是通过二叉树的先序遍历 来得到 类别的,不使用递归。这种方法在 全部查询出 类别的时候,是很简单的。

    先看数据库表格的设计。

    id name lft rht father_id layer
    1 顶级分类 1 4 0 0
    2 网站底部 2 3 1 1

    注释:

      id   ---     类别id

         name  ------   类别名称

      lft      ------   左值(left 和right 在mysql 中是关键字,所以用lft 和 rht 来代替)

      rht    -----     右值

      father_id-------   父类的ID

      layer--------       层数(第几层)

    现在我们来遍历 二叉树。

    左值和右值。

    那么某个节点到底有多少子孙节点呢?很简单,子孙总数 =(右值-左值-1)/2 

    以节点“底部”举例,其子孙总数=(7-2-1)/ 2 = 2  就是 有2 个子孙节点。

    类别的增、删、改、查。

    类别的增加:

    增加,分为两种情况,一是增加顶级分类,即是 新增节点的父类是“顶级分类”,在这种情况下,只需要 将顶级节点的右值加上2.更新一下,然后将该节点的左值等于原“顶级分类”的右值,新增节点的右值=父类的右值+1,增加该节点即可;二是增加的节点是其他顶级分类的子节点,如在“公告”节点下 再新增一个节点——‘公告2’,规则为大于该新增节点的父节点的 右值 都 +2,如 以上的例子,新增节点“公告2”,那么 图为 ;

            

     

    左值 都没有改变。大于11(“公告”右值)的都 +2了。

    代码如下:

     

     

    public function actionAdd(){
           // var_dump($_POST);die();
            if(isset($_POST)){
                $n = $_POST['cate'];
                $fid = $_POST['catefather_id'];
                $bath = dirname(Yii::app()->BasePath);
                $img = Articlecategory::upFile($_FILES,"$bath/uploads/article/",'jpg,png');
               // var_dump($img);
                //echo $img[0];
                //die();增加顶级分类
                if($fid ==1){
    
                    $cate = Articlecategory::model()->find('id=:id',array(":id"=>$fid));
                    $f_rgt = $cate['rht'];
                    $c = Articlecategory::model()->updateByPk($fid,array('rht'=>$f_rgt+2));
                    $articlecate = new Articlecategory();
                    $articlecate->name = $n;
                    $articlecate->img_url = "/uploads/article/"."$img[0]";
                    $articlecate->img_name = $img[0];
                    $articlecate->father_id = $fid;
                    $articlecate->lft =$f_rgt;
                    $articlecate->rht = $f_rgt+1;
                    $articlecate->layer = 2;
                    $i = $articlecate->save();
                    //var_dump($i);die();
    
                }else{
                    //echo 2;
              //给顶级分类 增加子节点。
    $cate = Articlecategory::model()->find('id=:id',array(":id"=>$fid)); $f_rgt = $cate['rht']; $f_lft = $cate['lft']; $layer = $cate['layer']; //echo $f_rgt;die(); $ar = Articlecategory::model()->findAll("rht > :rht ",array(":rht"=>$f_rgt-1)); //var_dump($ar);die(); foreach($ar as $v){ $v->rht = $v->rht +2; $v->update(); } $ar2 = Articlecategory::model()->findAll('lft > :lft',array(":lft"=>$f_rgt)); foreach($ar2 as $v2){ $v2->lft = $v2->lft +2; $v2->update(); } //var_dump($c); // echo $f_lft;echo $f_rgt;die(); $articlecate = new Articlecategory(); $articlecate->name = $n; $articlecate->father_id = $fid; $articlecate->lft =$f_rgt; $articlecate->rht = $f_rgt+1; $articlecate->layer = $layer+1; $articlecate->img_url = "/uploads/article/"."$img[0]"; $articlecate->img_name = $img[0]; $i = $articlecate->save(); //var_dump($i);
    } if($i){ $this->redirect('index'); } } }

     

     

    类别的删除

    类别的删除,主要是看 要删除的该节点是否有子节点。如果有子节点,是否需要将子节点也一块删除。

     

    代码如下:

     

      //删除 类别
     public function actionDel(){
            $id = $_POST['id'];
            //$id = $_GET['id'];
            /*
             * 先判定 该节点是否有子类
             */
            
    
            $articlecategory_1 = Articlecategory::model()->find("id = :id",array(":id"=>$id));
            $y_rht = $articlecategory_1['rht'];
            $y_lft = $articlecategory_1['lft'];
            $father = $articlecategory_1['father_id'];
         // 1:得到该节点下的子孙节点的个数
            $criteria = new CDbCriteria();
            $criteria->addBetweenCondition('lft', $y_lft, $y_rht);//
            $criteria->order = "lft asc";
            $criteria->addNotInCondition('id',array($id));//去除本节点。
            $son = Articlecategory::model()->findAll($criteria);
            $count = count($son);
    
                if($count == 0){//没有子孙节点的节点 
                    $i = Articlecategory::model()->find('id = :id',array(':id'=>$id));
                    $yuan_lft = $i['lft'];//本节点的左值
                    $yuan_rht = $i['rht'];//本节点的右值
                    $father_id = $i['father_id']; //本节点的父节点 id 
                    Articlecategory::model()->find('id = :id',array(':id'=>$id))->delete();//删除该节点
                    $a =Articlecategory::model()->find("id = :id",array(":id"=>$father_id));
                    $node_lft = $a['lft'];//父节点的左值
                    $node_rht = $a['rht'];//父节点的右值
              //左值 >本节点左值的 所有值的 左值 -2; 右值 > 本节点的右值 也全部-2;
                    $Articlecate = Articlecategory::model()->findAll("lft > :lft",array(":lft"=>$yuan_lft));
                    foreach($Articlecate as $v1){
                        $v1->lft = $v1->lft - 2;
                        $i = $v1->update();
                    }
                    $article = Articlecategory::model()->findAll("rht > :rht",array(":rht"=>$yuan_rht));
                    foreach($article as $v2){
                        $v2->rht = $v2->rht -2;
                        $j = $v2->update();
                    }
                }else{
             //删除本节点的子孙节点 Articlecategory
    ::model()->deleteAll($criteria); $n = ($count+1)*2;// (n+1)*2, n 是该节点的子孙个数. //该节点的父节点 所有右值 >=该右值的所有右值-(n+1)*2 $articlecategory_2 =Articlecategory::model()->find("id = :id",array(":id"=>$father)); $rht = $articlecategory_2['rht'];//该父节点的右值; $lft = $articlecategory_2['lft'];//该父节点的左值; $i = Articlecategory::model()->find('id = :id',array(':id'=>$id))->delete();//删除本节点 //全部左值>父节点右值 的 左值 全部要减去 $n. $model = Articlecategory::model()->findAll("lft > :lft",array(":lft"=>$rht)); foreach($model as $v){ $v->lft = $v->lft - $n; $i = $v->update(); }
             //全部右值 >本节点的右值的所有 右值 要减去$n。
    $model_2 = Articlecategory::model()->findAll("rht > :rht",array(":rht"=>$y_rht)); foreach($model_2 as $m){ $m->rht = $m->rht - $n; $j = $m->update(); } }

     

    类别的修改

    这个是花费时间最长的一个。

    主要分为两类。1 向前移动

           2 向后移动

    贴代码

     public function actionUpdate(){
            //print_r($_POST);die();
            $id = $_GET['id'];//该节点的id
            $bath = dirname(Yii::app()->BasePath);
            $img = Articlecategory::upFile($_FILES,"$bath/uploads/article/",'jpg,png');
            // 该节点现在的左右值。  更新该节点的名字和父id
            $node_articlecategory1 = Articlecategory::model()->find("id = :id",array(":id"=>$id));
            $node_articlecategory1->name = $_POST['name'];
            $node_articlecategory1->img_url = "/uploads/article/"."$img[0]";
            $node_articlecategory1->img_name = $img[0];
            $node_articlecategory1->father_id = $_POST['catefather_id'];
            $i = $node_articlecategory1->update();
            $node_lft = $node_articlecategory1['lft'];//节点 左值
            $node_rht = $node_articlecategory1['rht'];//节点 右值
            $node_layer = $node_articlecategory1['layer'];//节点 层数
            $old_f_id = $_GET['f_old']; //原本的父id
            $new_f_id = $_POST['catefather_id'];//新更新的父id
    ////得到该节点的子孙节点个数。 //$sql = "select * from xv_articlecategory where Lft between ".$node_lft." and ".$node_rht." order by Lft asc"; $criteria = new CDbCriteria(); $criteria->addBetweenCondition('lft', $node_lft, $node_rht);// $criteria->order = "lft asc"; $criteria->addNotInCondition('id',array($id));//去除本节点。 $son = Articlecategory::model()->findAll($criteria); // var_dump($son);die(); $n = count($son);
         //得到新更新父id的信息
    $new_articlecategory = Articlecategory::model()->find("id = :f_id",array(":f_id"=>$new_f_id)); $new_lft = $new_articlecategory['lft'];///该节点 新的父类的节点 左右值 层数 $new_rht = $new_articlecategory['rht']; $new_layer = $new_articlecategory['layer'];
         //得到原来父id的信息
    $old_articlecategory = Articlecategory::model()->find("id = :f_id",array(":f_id"=>$old_f_id)); $old_lft = $old_articlecategory['lft']; $old_rht = $old_articlecategory['rht'];////该节点 原来的父类 节点左右值。 $old_layer = $old_articlecategory['layer']; //echo $new_rht; if($new_rht > $old_rht){ /* * 向后移动 */
            //所有的左值 是 本节点_右值 < left < 新父节点_右值 全部-($n+1)*2;
    $lft_articlecategory= Articlecategory::model()->findAll("lft>$node_rht and lft < $new_rht "); //var_dump($lft_articlecategory); die(); foreach($lft_articlecategory as $v1){ //$v1->lft = $v1->lft - ($n+1)*2; $v1->lft = $v1->lft - ($n+1)*2; $i = $v1->update(); //echo $i; }
            //所有的右值 是 本节点_右值< rht < 新父节点_右值 全部-($n+1)*2;
    $rht_articlecategory = Articlecategory::model()->findAll("rht>$node_rht and rht < $new_rht"); //var_dump($rht_articlecategory); foreach($rht_articlecategory as $v2){   $v2->rht = $v2->rht - ($n+1)*2;  $j = $v2->update(); // echo $j; //die(); }
           //更新本节点的左右值
    $node_articlecategory = Articlecategory::model()->find("id = :id",array(":id"=>$id)); $node_articlecategory->rht = $new_rht-1; $node_articlecategory->lft = ($new_rht-1) - (2*$n+1);///是根据公式 子孙总数 = (右值 - 左值 -1)/2 $node_articlecategory->layer = $new_layer+1; $node_articlecategory->father_id = $new_f_id; $node_articlecategory->update(); $l = $old_articlecategory['layer'] - $new_articlecategory['layer'];/// 层数的计算:是为子孙 节点 的层数 做打算。 $son_n =($new_rht-1)-$node_rht; // 本节点_原来_右值 - 本节点_现在_右值 = 差值。差值 也是 子孙节点的差值。 foreach($son as $v3){ $v3->lft = $v3->lft + $son_n; $v3->rht = $v3->rht + $son_n; $v3->layer = $v3->layer - $l; $v3->update(); } }elseif($new_rht < $old_rht){ /* * 向前移动 */ $lft_articlecategory= Articlecategory::model()->findAll("lft>$new_rht-1 and lft < $node_lft "); //var_dump($lft_articlecategory); foreach($lft_articlecategory as $v1){ $v1->lft = $v1->lft +($n+1)* 2; $v1->update(); } $rht_articlecategory = Articlecategory::model()->findAll("rht>$new_rht-1 and rht < $node_lft"); foreach($rht_articlecategory as $v2){ $v2->rht = $v2->rht +($n+1)* 2; $v2->update(); } //echo $new_rht;die(); $f_rht = Articlecategory::model()->find('id = :id',array(":id"=>$new_f_id));
    $node_articlecategory = Articlecategory::model()->find("id = :id",array(":id"=>$id)); $node_articlecategory->rht = $new_rht + (2*$n+1); $node_articlecategory->lft = $new_rht; $node_articlecategory->layer = $new_layer+1; $node_articlecategory->father_id = $new_f_id; $node_articlecategory->update(); // var_dump($node_articlecategory);die(); $l = $old_layer - $new_layer; $son_n =abs(($new_rht + (2*$n+1))-$node_rht) ; foreach($son as $v3){ $v3->lft = $v3->lft - $son_n; $v3->rht = $v3->rht - $son_n; $v3->layer = $v3->layer - $l; $v3->update(); } } }

     

  • 相关阅读:
    centos7手动搭建redis集群
    Xshell突破四个窗口限制
    Redis官方集群规范
    Redis官方集群教程
    centos7 更新阿里YUM源
    gitlab配置ssh
    Java前端控制器模式~
    Java数据访问对象模式
    Java组合实体模式~
    Java业务代理模式~
  • 原文地址:https://www.cnblogs.com/xiaoxiao2014/p/3833579.html
Copyright © 2011-2022 走看看