一般情况下排序是交给前端来实现的,后端一般主要是实现数据库的增删查改。但是PHP中经常出现order字段,由于后端排序order方法的存在,这样排序实现起来会更加简单,有些时候考虑到前端压力,也会将排序交给后端完成。
既然是数据排序,少不了获取数据,因此回到app/controller/User.php中找到index方法,在withSearch搜索器中增加create_time方法,加上之前的查询方法得到如下代码:
public function index(){
return View::fetch('index',[
'list'=>UserModel::withSearch(['gender','username','email','create_time'],[
'gender'=>request()->param('gender'),
'username'=>request()->param('username'),
'email'=>request()->param('email'),
'create_time' => request()->param('create_time')
])->paginate([
'list_rows'=>5,
'query' => request()->param()
])
]);
}
之后在app/model/User.php中增加如下方法:
//时间排序搜素器
public function searchCreateTimeAttr($query,$value){
return $value ? $query->order('create_time',$value):'';
}
在导航栏写入localhost/index.php/user?create_time=desc回车得到如下效果:
解释:这种方式即为get传参,传递参数create_time=‘desc’给后端,后端通过request()->param()的助手函数得到参数值’desc’,并将该参数传递给后端model的SearchCreateTimeAttr()方法(通过第二个参数$value传递),这样才依次完成搜索和排序过程。
接下来,我们希望能够实现点击创建时间便能够直接进行排序,修改UI,进入app/View/User/index.html文件中,将"创建时间"一栏改成如下代码:
<th class="text-center dropup">
<a href="{:url('/user')} ? create_time={$orderRule}" class="text-secondary order-style dropdown-toggle">创建时间 <span class="caret"></span></a>
</th>
为了实现实际切换,在fetch中加入参数方式:
'orderRule' => request()->param('create_time')=='desc'? 'asc':'desc'
上述方式虽然能够实现排序,但是存在一些问题。比如在跳转到page=3的时候,点击使用时间排序之后默认会跳转到第一页。而在实际情况下,排序是不需要回到第一页的。下面对这种方式进行一波优化。
首先,由于page本身也占用了参数位,故而考虑使用助手函数request()->url()获取在排序之前的url路径:
<a href="{:request()->url(true)}?create_time={$orderRule}" class="text-secondary order-style dropdown-toggle">创建时间 <span class="caret"></span></a>
但是,很显然在逻辑上也存在矛盾的地方,比如之前说的能够按照时间正序排序也能够按照时间倒序排序。如果按照这样那么就会出现如下问题:
暴露两大问题:(1)参数重复;(2)url中的’?‘与’&'有误。
针对问题上述问题,采取的方式是原生PHP处理url参数,具体实现方式如下:
为了提高函数的可重用性,在common下新建一个Tool.php,在其中写入如下代码:
namespace app\common;
class Tool{
public static function url($queryString){
//获取当前路径url
$urlFull=request()->url(true);
//检测是否含有参数,没有参数加上?返回,防止将参数转化为数组是undefined报错
if(!isset(parse_url($urlFull)['query'])){
return $urlFull.'?';
}
//将url转化成数组并提取其中的查询参数
$query=parse_url($urlFull)['query'];
//将查询字符串转化成拼接成数组,这个过程能够去除重复参数(后出现的覆盖之前出现的)
parse_str($query,$urlArr);
//删除里面的create_time参数,因为之后的create_time是默认会加上的,多余的参数也会被之后覆盖
unset($urlArr[$queryString]);
//将数组重新合成url
$queryAll=http_build_query($urlArr);
return request()->domain().request()->baseUrl().'?'.$queryAll.'&';
}
}
通过字符串转数组,数组拼接字符串能够巧妙地实现去除重复参数,通过isset()函数和unset去除数组字段,能够解决’?‘与’&'问题,直接起飞,最终效果如下: