本书未发布

63. 话题列表排序

未匹配的标注

简介

在本节里,我们完成话题列表可以按『最后回复』和『最新发布』排序功能。

需求分解

我们可以通过 URI 传参 order 给控制器,控制器根据此参数来决定数据的读取逻辑。因为『分类下的话题列表』也会用到排序,并且是在不同的控制器中,所以在此处为了复用性考虑,我们将会把排序逻辑代码放置于 Topic 数据模型中。

在 Topic 数据模型里我们打算用 查询范围 实现排序功能。查询范围允许我们定义通用的约束集合以便在应用中复用。要定义这样的一个查询范围,只需简单在对应的模型方法前加上一个 scope 前缀,查询范围总是返回 查询构建器。一旦定义了查询范围,则可以在查询模型时调用该查询范围方法。需要注意的是在进行方法调用时不需要加上 scope 前缀。

此外,从 V5.1.26+ 版本开始,支持在数据模型里面可以设置 globalScope 属性,定义 全局查询范围全局查询范围 和普通查询范围不同之处是,当给模型设置了全局查询范围后在执行查询操作时不通过 useGlobalScope方法关闭时全局查询默认是有效的(即给查询添加上全局查询范围条件)。

数据模型

application/common/model/Topic.php

<?php

namespace app\common\model;

use think\Model;

class Topic extends Model
{
    .
    .
    .
    /**
     * 范围查询-最近回回复排序
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2019-02-25
     * @param    [type]             $query 查询构建器
     * @return   [type]                    查询构建器
     */
    public static function scopeRecentReplied($query)
    {
        // 按最后更新时间排序
        return $query->order('update_time', 'DESC');
    }

    /**
     * 范围查询-最新发表
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2019-02-25
     * @param    [type]             $query 查询构建器
     * @return   [type]                    查询构建器
     */
    public static function scopeRecent($query)
    {
        // 按照创建时间排序
        return $query->order('id', 'DESC');
    }

    /**
     * 范围查询-排序方式
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2019-02-25
     * @param    [type]             $query      查询构建器
     * @param    [type]             $order_type 排序方式
     * @return   [type]                         查询构建器
     */
    public static function scopeWithOrder($query, $order_type)
    {
        switch ($order_type) {
            case 'recent':
                $query->recent();
                break;
            default:
                // 默认按最后回复降序排列
                $query->recentReplied();
                break;
        }

        return $query->with('user,category');
    }

    /**
     * 分页查询方法
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2019-06-20
     * @param    array              $params    请求参数
     * @param    integer            $page_rows 每页显示数量
     * @return   [type]                        分页查询结果
     */
    public static function minePaginate($param = [], $per_page = 20)
    {
        $order_type = NULL;
        if(isset($param['order'])){
            $order_type = $param['order'];
        }
        $self = self::withOrder($order_type);

        foreach ($param as $name => $value) {
            switch ($name) {
                case 'category_id':
                    if($value > 0){
                        $self = $self->where($name, $value);
                    }
                    break;
            }
        }
        $paginate = $self->paginate($per_page);
        return $paginate;
    }
}

控制器

接下来,我们在话题控制器中调用 minePaginate 时把排序参数(我们这里设置的参数名是 order )传递进去。

  1. 话题列表:

application/index/controller/Topic.php

<?php

namespace app\index\controller;

use think\Request;
use app\common\model\Topic as TopicModel;

class Topic extends Base
{
    public function index(Request $request)
    {
        $param = $request->only(['order'], 'get');
        $paginate = TopicModel::minePaginate($param);
        $this->assign('paginate', $paginate);

        return $this->fetch('index');
    }
}
  1. 分类话题列表:

application/index/controller/Category.php

<?php

namespace app\index\controller;

use think\Request;

use app\common\model\Topic as TopicModel;
use app\common\model\Category as CategoryModel;

class Category extends Base
{
    /**
     * 显示指定的资源
     *
     * @param  int  $id
     * @return \think\Response
     */
    public function read(Request $request, $id)
    {
        $category = CategoryModel::find($id);
        $this->assign('category', $category);

        $param = $request->only(['order'], 'get');
        $param['category_id'] = $id;
        $paginate = TopicModel::minePaginate($param);
        $this->assign('paginate', $paginate);

        return $this->fetch('topic/index');
    }
}

代码解读

  • 在这里我们使用 $request->only 方法只获取请求 URL 里的 order 这一个参数值并把它传递到 minePaginate 方法里;
  • 当使用 $request->only 获取的请求参数不存在时,返回结果里不包含该参数主键,如当参数 order 不存在时 $param = $request->only(['order'], 'get') 的运行结果是 $param = [];

助手方法

接下来,我们需要添加一个辅助方法为当前使用的排序方式添加上选中效果。

application/index/common.php

<?php
.
.
.
/**
 * 排序方式导航是否active样式名
 * @Author   zhanghong(Laifuzi)
 * @DateTime 2019-02-25
 * @param    string             $name     判断参数名
 * @param    string             $value    判断参数值
 * @param    boolean            $is_equal 判断方式
 * @return   string                       [description]
 */
function order_active($name, $value, $is_equal = true)
{
    // 获取当前请求信息里的参数值
    $param_value = request()->get($name);
    $is_active = false;
    if($is_equal == true && $param_value == $value){
        // 页面请求参数值和判断参数值相等时为选中样式
        $is_active = true;
    }else if($is_equal != true && $param_value != $value){
        // 页面请求参数值和判断参数值不等时为选中样式
        $is_active = true;
    }

    if($is_active){
        return 'active';
    }else{
        return '';
    }
}

视图页面

接下来,在视图页面里我们需要为按钮添加链接和选中状态。

application/index/view/topic/index.html

<div class="card-header bg-transparent">
    <ul class="nav nav-pills">
        <li class="nav-item">
            <a class="nav-link <?php echo(order_active('order', 'recent', false)); ?>" href="<?php echo(request()->baseUrl()); ?>">
                最后回复
            </a>
        </li>
        <li class="nav-item">
            <a class="nav-link <?php echo(order_active('order', 'recent')); ?>" href="<?php echo(request()->baseUrl()); ?>?order=recent">
                最新发布
            </a>
        </li>

    </ul>
</div>

代码解读

效果展示

Git 版本控制

下面把代码纳入到版本管理:

$ git add -A
$ git commit -m "话题排序"

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~