#Practice 自定义筛选条件

Grid view 搭配 search model 可以很方便地筛选数据。通常情况下,筛选情况分两种:精确筛选和模糊筛选。前者常见于 ID, 模型状态值等;后者用于关键字搜索(例如搜索客户名称)。Yii 应用通常使用时间戳来存储时间,好处是精简,且能使用 formatter 组件显示人性化的时间。使用时间戳来存储时间的一个不便之处在于,筛选数据比较麻烦,不管是精确筛选还是模糊筛选,都不适合。

场景一:筛选某个时间段内的记录

假设我们有一个订单表,使用 created_at 列表示订单创建时间,该列使用时间戳存储时间。首先做一个自定义的下拉菜单作为该字段的 filter. options 如下: ['thisweek' => '本周', 'lastweek' => 上周. 当用户选择“本周”时, url 大致如下: order/index?Order[created_at]=thisweek. query params 会通过 search model 的 search() 存储到 $searchModel 内。注意,此时 $searchModel->created_at 的值类型是字符串,和 order 模型声明的类型(整数)不同。不过我们并不打算写入数据库,我们需要在 search model 的 rules 内将 created_at 列设置为 safe.

接下来对 filter condition 稍作处理:当 $searchModel->created_at 值存在时,我们将这个自定义的字符串转换成 SQL 语句。例如:

if (!empty($this->created_at)) {

list($start, $end) = converter('thisweek'); // converter 是自己写的转换器,

$query->andFilterWhere(['BETWEEN', '{{%income}}.created_at', $start, $end)]);

}

场景二:筛选超过一个月没联系的客户

假设我们使用 customer.last_active_time 存储客户的最后活动时间,该列同样使用时间戳存在数据库内。和场景一类似,filter 我们仍做一个下拉菜单,options 有 'over30days' => '超过30天未联系' 等。唯一的区别是选用的 SQL 语句不同:

if (!empty($this->last_active_time)) {

$query->needToInteract();

}

needToInteract() 在 CompanyQuery 内定义:

public function needToInteract($day = 40)

{

return $this->andWhere([

'<',

'{{%company}}.last_active_time',

(time() - 60 * 60 * 24 * $day)

]);

}

因为前面已经断定 last_active_time 至存在,因此可以直接使用 andWhere() 而不是 andFilterWhere().

小结

自定义筛选可能让我们能创造更人性化的筛选条件。要点:自定义 filter dropdown options; search model 内 rules() 确保 safe; search() 内根据值转化出对应的查询语句。

你可能感兴趣的:(#Practice 自定义筛选条件)