dd

thinkphp实现左右值增、改、删操作类

jerry JQuery 2015年11月18日 收藏
新手,写了基本功能,未写排序等相关操作;求高手改进,
数据库:

类库文件:
Category.class.php
<?php
/**
应用基于thinkphp的左右值无限分类
**/
class Category
{
    //传入实化的对象【M('表名')】
    private $objCategory;
    //基础节点ID号
    public $intCurrentId;
    //设置制表符样式
    private $arrTabsStyle = array(
                            'indent' => '   ',
                            'process' => '├ ',
                            'end'=>'└ '
                        );
    //构造函数初始化
    public function __construct($objCategory)
    {
        $this->objCategory = $objCategory;
    }
    //验证传入ID【大于0的数字】
    private function checkFun($intId)
    {
        //$intId优先验证
        if(isset($intId))
        {
            $this->intCurrentId = $intId;
            return true;
        }
        //如果$this->intCurrentId 已设置,验证
        else
        {
            if(isset($this->intCurrentId))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
    //根据ID号获取当前节点左右值
    private function setCurrentData($intId)
    {
        if(false == $this->checkFun($intId))
        {
            return false;
        }
        $map['id'] = $this->intCurrentId;
        return $this->objCategory->field(array('lft','rgt'))->where($map)->find();
    }
    /*
    *作用:
        设置输出列表数据的制表符样式
    *参数:
        $key:arrTabsStyle的KEY
        $value:arrTabsStyle的值
    */
    public function setTabStyle($key, $value = '')
    {
        if(isset($this->arrTabsStyle[$key]))
        {
            $this->arrTabsStyle[$key] = $value;
        }
    }
    /*
    *作用:
        根据ID号获取当前节点数据
    *参数:
        $intId:可设置的,需读取节点ID号
    */
    public function getCurrentData($intId)
    {
        if(false == $this->checkFun($intId))
        {
            return false;
        }
        $map['id'] = $this->intCurrentId;
        return $this->objCategory->field(array('id','title'))->where($map)->find();
    }
    /*
    *作用:
        获取当前节点的父节点数据
    *参数:
        $intId:需要读取节点的ID
    */
    public function getParentCategoryData($intId)
    {
        $arrRoot = $this->setCurrentData($intId);
        if($arrRoot)
        {
            $map['lft'] = array('LT', $arrRoot['lft']);
            $map['rgt'] = array('GT', $arrRoot['rgt']);
            return $this->objCategory->where($map)->find();
        }
        else
        {
            return false;
        }
    }
    /*
    *作用:
        获取ID下节点列表
    *参数:
        $intId:需要读取节点的父ID
        $intLevel:目录等级默认到100级
    */
    public function getCategoryList($intId = 1, $intLevel = 100)
    {
        //获取选定节点左右值,得出取值区间
        $arrRoot = $this->setCurrentData($intId);
        if($arrRoot)
        {
            //读取数据库符合条件的数据
            $map['lft'] = array('BETWEEN', array($arrRoot['lft'], $arrRoot['rgt']));
            $arrChildList = $this->objCategory->where($map)->order('lft')->select();
            //return $arrChildList;
            //对取出数据进行格式化
            $arrRight = array();
            foreach($arrChildList as $v)
            {
                
                if(count($arrRight))
                {
                    while ($arrRight[count($arrRight) - 1] < $v['rgt'])
                    {
                        array_pop($arrRight);
                    }
                }
                //设置读取目录等级
                if($intLevel > count($arrRight))
                {
                    $title = $v['title'];
                    //设置输出时的样式
                    if(count($arrRight))
                    {
                        $title = $this->arrTabsStyle['process'].$title;
                    }
                    $title = str_repeat($this->arrTabsStyle['indent'], count($arrRight)).$title;
                    $returnCategoryList[] = array('id'=>$v['id'],'title'=>$title,'lft'=>$v['lft'],'rgt'=>$v['rgt']);
                    $arrRight[]  = $v['rgt'];
                }
            }
            return $returnCategoryList;
        }
        return false;
    }
    /*
    *作用:
        获取节点的子节点数
    *参数:
        $intId:需要读取节点的父ID
    */
    public function getCategoryCount($intId)
    {
        $arrRoot = $this->setCurrentData($intId);
        return ($arrRoot['rgt'] - $arrRoot['lft'] - 1) / 2;
    }
    /*
    *作用:
        添加节点
    *参数:
        $bolType:true添加到节点前面,false添加到节点尾部
        $intId:添加到的父节点
    */
    public function insertCategory($bolType = false, $intPid)
    {
        $data = I('param.');
        if(!isset($intPid))
        {
            $intPid = $data['pid'];
        }
        $arrRoot = $this->setCurrentData($intPid);
        if($arrRoot)
        {
            if($bolType)
            //true添加到节点前面
            {
                $this->objCategory->where('rgt>'.$arrRoot['lft'])->setInc('rgt',2);
                $this->objCategory->where('lft>'.$arrRoot['lft'])->setInc('lft',2);
                //设置当前节点的左右值
                $data['lft'] = $arrRoot['lft'] + 1;
                $data['rgt'] = $arrRoot['lft'] + 2;
            }
            else
            //false添加到节点尾部
            {
                $this->objCategory->where('rgt>='.$arrRoot['rgt'])->setInc('rgt',2);
                $this->objCategory->where('lft>'.$arrRoot['rgt'])->setInc('lft',2);
                $data['lft'] = $arrRoot['rgt'];
                $data['rgt'] = $arrRoot['rgt'] + 1;
            }
            return $this->objCategory->add($data);
        }
        else
        {
            return false;
        }
    }
    /*
    *作用:
        删除节点
    *参数:
        $intId:被删除的节点ID
    */
    public function deleteCategory($intId)
    {
        $arrRoot = $this->setCurrentData($intId);
        if($arrRoot)
        {
            $ints = $arrRoot['rgt'] - $arrRoot['lft'] + 1;
            $map['lft'] = array('BETWEEN', array($arrRoot['lft'], $arrRoot['rgt']));
            $this->objCategory->where($map)->delete();
            $this->objCategory->where('lft>'.$arrRoot['rgt'])->setDec('lft',$ints);
            $this->objCategory->where('rgt>'.$arrRoot['rgt'])->setDec('rgt',$ints);
            return true;
        }
        else
        {
            return false;
        }
    }
    /*
    *作用:
        更新节点
    *参数:
        $intId:被删除的节点ID
    */
    public function updateCategory()
    {
        //读取POST数据存入数组
        $data = I('param.');
        //父ID等于子ID,直接跳出
        if($data['pid'] == $data['id']){return false;}
        //post.pid和当前父post.old相等说明未改变目录,不更新左右值
        if($data['pid'] !== $data['oldpid'])
        {
/**********************************【读取所需的相关值】********************************/
            //获取新的父节点的数据
            $arrParent = $this->setCurrentData($data['pid']);
            //取当前节点的数据
            $arrCurrent = $this->setCurrentData($data['id']);
/* 任务:删除节点 */
/**********************************【A-1:隔离数据】************************************/
            //将需要调整位置的左右值+100000
            $map['lft'] = array(
                        array('EGT', $arrCurrent['lft']),
                        array('ELT', $arrCurrent['rgt'])
                    );
            $this->objCategory->where($map)->setInc('lft',100000);
            //因为左值已更新,所以条件变化+100000
            $map['lft'] = array(
                        array('EGT', $arrCurrent['lft'] + 100000),
                        array('ELT', $arrCurrent['rgt'] + 100000)
                    );
            $this->objCategory->where($map)->setInc('rgt',100000);
            unset($map);
/**********************************【A-2:更新正常节点值】******************************/
            //获取隔离节点后续更新的步长值
            $intStep = $arrCurrent['rgt'] - $arrCurrent['lft'] + 1;
            //更新节点左右值
            $map['lft'] = array(
                        array('GT', $arrCurrent['rgt']),
                        array('LT', 100000)
                    );
            $this->objCategory->where($map)->setDec('lft',$intStep);
            unset($map);
            $map['rgt'] = array(
                        array('GT', $arrCurrent['rgt']),
                        array('LT', 100000)
                    );
            $this->objCategory->where($map)->setDec('rgt',$intStep);
            unset($map);
/* 完成:删除节点 */
/* 任务:更新节点 */
/**********************************【B-1:新父节目点提供下级节点的空间】****************/
            $map['lft'] = array(
                        array('GT', $arrParent['lft']),
                        array('LT', 100000)
                    );
            $this->objCategory->where($map)->setInc('lft',$intStep);
            unset($map);
            $map['rgt'] = array(
                        array('GT', $arrParent['lft']),
                        array('LT', 100000)
                    );
            $this->objCategory->where($map)->setInc('rgt',$intStep);
            unset($map);
/**********************************【B-2:将节点放入指定下级的空间】********************/
            //获取隔离节点后续更新的步长值
            $intStep = 100000 + ($arrCurrent['lft'] - ($arrParent['lft'] + 1));
            //更新左右值大于父节点左值的节点的左右值
            $map['lft'] = array(
                        array('EGT', $arrCurrent['lft'] + 100000),
                        array('ELT', $arrCurrent['rgt'] + 100000)
                    );
            $this->objCategory->where($map)->setDec('lft',$intStep);
            unset($map);
            $map['rgt'] = array(
                        array('EGT', $arrCurrent['lft'] + 100000),
                        array('ELT', $arrCurrent['rgt'] + 100000)
                    );
            $this->objCategory->where($map)->setDec('rgt',$intStep);
        }
        return $this->objCategory->where('id='.$data['id'])->setField('title', $data['title']);
    }
}
?>
使用:
<?php
class CategoryAction extends CommonAction {
    private $objCG;
    public function _initialize(){
        //导入分类库
        import('@.ORG.Util.Category');
        $this->objCG = new Category(M('CommonCategory'));
    }
    //目录列表
    public function index($id = 1){
        $this->cateorylist = $this->objCG->getCategoryList($id);
        $this->display();
    }
    //添加目录
    public function add($id=1){
        $this->cateorylist = $this->objCG->getCategoryList($id);
        $this->display();
    }
    //编辑目录
    public function edit($id){
        if (!empty($id)){
            //输出所有的节点
            $this->cateorylist = $this->objCG->getCategoryList(1);
            //读取当前节点数据
            $vo = $this->objCG->getCurrentData($id);
            if ($vo){
                //读取当前节点的父节点数据
                $arrParent = $this->objCG->getParentCategoryData($id);
                $vo['pid'] = $arrParent['id'];
                $this->assign('vo',$vo);
                $this->display();
            }else{
                $this->error('数据不存在!');
            }
        }else{
            $this->error('数据不存在!');
        }
    }
    //添加目录:操作
    public function insert(){
        $list = $this->objCG->insertCategory();
        if ($list !== false)
        {
            $this->success('数据保存成功!');
        }
        else
        {
            $this->error('数据写入错误!');
        }
    }
    public function delete($id){
        if (!empty($id))
        {
            $result = $this->objCG->deleteCategory($id);
            if ($result)
            {
                $this->success('删除成功!');
            }
            else
            {
                $this->error('删除出错!');
            }
        }
        else
        {
            $this->error('ID错误!');
        }
    }
    public function update(){
        $list = $this->objCG->updateCategory();
        if ($list !== false)
        {
            $this->success('更新成功!');
        }
        else
        {
            $this->error("操作失败!");
        }
    }
}
dd