要实现数据的任意排序需要满足以下条件:
每条数据有唯一的排序值,这个可以添加时取当前最大(或最小)的排序值加一(或减一)获取
输入:
id:要排到其他位置的数据ID
target_id:数据被插入的目标ID
带附号形式,如'+10', '-12',数字形式,如'17'
数据:
sort_order: 排序值
流程:
1.获取数据(id)的sort_order到s1,
2.获取数据(target_id,去掉符号)的sort_order到s2,
3.如果target_id带符号,则取它之前(符号为'-'时)或之后(符号为'+'时)的sort_order到s2
4.把所有sort_order在s1和s2的数据的sort_order加一(s2 < s1时)或减一(s2 > s1时)
5.把数据(id)的sort_order更新为s2
以下是php版本的代码
1 public function sort($where, $id, $target_id){ 2 $b = false; 3 $this->startTrans(); 4 $sort_order = $this->where(array_merge($where, array('id'=>$id)))->getField('sort_order'); 5 if($sort_order){ 6 /*查询定位记录的前、后、本身排序值*/ 7 $flag = ''; 8 if(is_string($target_id)){ 9 $flag = substr($target_id, 0, 1); 10 if($flag == '-' || $flag == '+') $target_id = substr($target_id, 1); 11 } 12 $target = $this->where(array_merge($where, array('id'=>$target_id)))->getField('sort_order'); 13 if($flag == '-' || $flag == '+'){ 14 $target = $this->where(array_merge($where, 15 array('sort_order '=>array($flag == '-'?'gt': 'lt', $target)) 16 ))->order($flag == '-'?'sort_order': ' sort_order desc')->getField('sort_order'); 17 } 18 if($target){ 19 if($target > $sort_order || $target < $sort_order){ 20 //两个排序值之间的排序值减/加一 21 $b = $this->where(array_merge($where, array('sort_order'=>array('between', $target > $sort_order?array($sort_order, $target): array($target, $sort_order))))) 22 ->execute('update %TABLE% set sort_order=sort_order'.($target > $sort_order?'-': '+').'1 %WHERE%', true); 23 } 24 if($b){ 25 $b = $this->where(array_merge($where, array('id'=>$id))) 26 ->execute('update %TABLE% set sort_order='.$target.' %WHERE%', true); 27 } 28 } 29 } 30 if($b){ 31 $this->commit(); 32 }else{ 33 $this->rollback(); 34 } 35 return $b; 36 }
本代码是使用ThinkPHP框架