简介


a,所谓排序,首先要利用到mysql中的order by
b,所谓自定义排序,需要建表的时候设定排序id字段//oid
c,排序字段的值要不唯一,可以随便改。这样才能依次排序。如果唯一,修改id后会发生跨越排序的现象。
d,结合上面,最适合插入的时候让oid和主键id一致。这样既有了初始排序,也互相修改,依次上升,依次下降。

核心代码


public function sort($obj,$handle,$id,$prefix)
{ 
    //根据传递的id查询出当前的oid(排序id);
    $map_sel_oid[$prefix.'id'] = $id;
    $oid = $obj
    ->field($prefix.'oid')
    ->where($map_sel_oid)
    ->find();
    $oid = $oid[$prefix.'oid'];
    //----------------------------------------------
    //这里的排序不仅仅是一般的排序,还有无限分类的排序,为了后续的顺利,给无限分类一个查询条件
    $arr = $obj->where($map_sel_oid)->find();
    //判断是否存在某键值
    $bool = array_key_exists($prefix.'fid',$arr);
    if($bool){ 
        $where[$prefix.'fid'] = $arr[$prefix.'fid'];
    }else{ 
        $where = "";
    }
    //----------------------------------------------
    //确定当前的id和oid
    $cur_id = $id;
    $cur_oid = $oid;
    $obj = $obj;
    //根据handle指针判断上移下移
    switch ($handle) {
        //指针为pre,表示上移
        case 'pre':
                //查询最大的oid,如果oid最大,则不能往上顶
                $max_oid = $obj
                ->where($where)
                ->order($prefix.'oid desc')
                ->field($prefix.'oid')
                ->find();
                $max_oid = $max_oid[$prefix.'oid'];

                //如果最大,那么不能往上顶了,后面的程序也不执行
                if($cur_oid == $max_oid){ 
                    $this->error('亲,这个已经是最顶部了');
                }else{
                    $preData = $this->preData($obj,$cur_oid,$prefix,$where);
                    dump($preData);

                    $pre_id = $preData[$prefix.'id'];
                    $pre_oid = $preData[$prefix.'oid'];
                    //查询了上一个的id和oid最后交换即可

                    $bools = $this->transOid($obj,$cur_id,$cur_oid,$pre_id,$pre_oid,$prefix);
                    if($bools){ 
                        $this->redirect('index');
                    }else{ 
                        $this->error('排序失败');
                    }
                }
            break;
        //指针为next,下移
        case 'next':
                //查询最小的oid,如果oid最小,则不能忘下移
                $min_oid = $obj
                ->where($where)
                ->order($prefix.'oid asc')
                ->field($prefix.'oid')
                ->find();
                $min_oid = $min_oid[$prefix.'oid'];
                if($cur_oid == $min_oid){ 
                    $this->error('亲,这已经是最底部了');
                }else{ 
                    $nextData = $this->nextData($obj,$cur_oid,$prefix,$where);
                    $next_id = $nextData[$prefix.'id'];
                    $next_oid = $nextData[$prefix.'oid'];

                    $bools = $this->transOid($obj,$cur_id,$cur_oid,$next_id,$next_oid,$prefix);
                    if($bools){ 
                        $this->redirect('index');
                    }else{ 
                        $this->error('排序失败');
                    }
                }
            break;
    }
}
//排序算法,查找上一个的id和oid
public function preData($obj,$oid,$prefix,$where)
{ 
    $oid = ++$oid;
    //$map[$prefix.'oid'] = $oid;
    $where[$prefix.'oid'] = $oid;
    $res = $obj
    ->where($where)
    ->field($prefix.'id'.','.$prefix.'oid')
    ->find();
    if($res){ 
        return $res;
    }else{ 
        return $this->preData($obj,$oid,$prefix);
    }

}
//排序算法,查找下一个的id和oid
public function nextData($obj,$oid,$prefix,$where)
{ 
    $oid = --$oid;
    //$map[$prefix.'oid'] = $oid;
    $where[$prefix.'oid'] = $oid;
    $res = $obj
    ->where($where)
    ->field($prefix.'id'.','.$prefix.'oid')
    ->find();
    if($res){ 
        return $res;
    }else{ 
        return $this->nextData($obj,$oid,$prefix);
    }
}
//交换id和oid
public function transOid($obj,$cur_id,$cur_oid,$else_id,$else_oid,$prefix)
{ 
    $map[$prefix.'id'] = $cur_id;
    $data[$prefix.'oid'] = $else_oid;
    $row = $obj->where($map)->save($data);
    if($row){ 
        $map[$prefix.'id'] = $else_id;
        $data[$prefix.'oid'] = $cur_oid;
        $row1 = $obj->where($map)->save($data);
        if($row1){ 
            return true;
        }else{ 
            return false;
        }
    }else{ 
        return false;
    }
}

调用代码


public function classSort()
{ 
    $handle = I('get.handle');
    $id = I('get.c_id');
    $prefix = 'c_';
    $this->sort($this->ClassObj,$handle,$id,$prefix);
}

流程简介


a,在视图的表格中写入上下的按钮,点击按钮的同时get方法带走需要操作的记录和指针
b,操作程序接收到之后,调用上述方法即可
c,调用的过程中,通过交换上下的oid(排序id)来进行排序

难点


a,在点击排序按钮的时候需要查询到隔壁记录的排序id,但是id在后期通过记录删除之后,不会是连续的,克服这个使用了递归算法。
b,当遇到无限分类排序的时候,父类子类孙类都在同一个表,导致查询的时候回混乱,克服这一难点,在查询的过程中使用了where条件。

并且做了判断,因为非无限分类表不需要where条件 c,为了避免繁杂,交换oid使用了一个方法,直接调用 d,为了避免极部无限递归下去,在最开始的时候直接做了判断,提高效率. 5,为了避免适应不同的表,加了字段前缀

不足


a,此类排序使用了递归直接操作数据库,加大了内存以及数据库的压力,所以仅仅用在分类,标签等等数据比较少,改动也比较少的表
b,上述核心方法表前缀应该在最开始的时候定义成变量,防止了以后的麻烦,也能适应更多的表(不用oid的为排序字段的表格)

说明


最近项目中用到排序,顺便使用了这种方法封装,这样后期需要排序的直接调用即可.博主也是抛砖引玉,希望有更好的方法讨论以及不足之处的指出.