文章出處

在網上也搜了很多的例子,根據網絡上的解釋,慢慢摸索,用了將近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(); } } }

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()