gridview使用hasmany关联获取groupby数据分类结果,并能做排序及搜索 [ 2.0 版本 ]
数据表结构
其中一个用户可以购买多个产品,由username关联buyer
members
userid 用户id
username 用户名
mobile 手机号 对手机号进行groupby
truename 真名 
trades
itemid 自增主键
buyer 买家
total 购买数量
amount 总额
status 交易状态
使用gii生成所需的模型Trades,Members;创建members的curd操作gridview
在Members模型里写入关联
class Members extends \app\models\Members
{
    public function getTrades()
    {
        return $this->hasMany(Trades::className(), ['buyer'=>'username']);
    }
}
在MembersSearch里写入查询语句及对应的属性值
class BigMembersSearch extends MembersSearch
{
    public $tradesCount;
    public $tradesTotal;
    public $tradesAmount;
    public $amountStart;
    public $amountEnd;
    // ...(其他需要自定义的属性,为gridview列的结果)
    public function rules()
    {
        $data = parent::rules();
        $data[] = [['tradesCount', 'tradesTotal', 'tradesAmount', 'amountStart', 'amountEnd'], 'double'];
        return $data;// 加入对应规则,否则不能进行索引及排序
    }
    public function search($params)
    {
        // 查询方法详细
        $query = self::find();
        $query->select([
            self::tableName().".userid",
            self::tableName().".username",
            self::tableName().".truename",
            self::tableName().".mobile",
            "COUNT(".Trades::tableName().".itemid) AS tradesCount",
            "SUM(".Trades::tableName().".total) AS tradesTotal",
            "SUM(".Trades::tableName().".amount) AS tradesAmount",
        ])->joinWith('trades')->groupBy([
            self::tableName().".mobile",
        ])->where([
            "LENGTH(".self::tableName().".mobile)"=>11,
            Trades::tableName().".status"=>[2, 3, 4],
        ]);
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);
        $dataProvider->sort->attributes['tradesCount'] = [
            'asc' => ["tradesCount" => SORT_ASC],
            'desc' => ["tradesCount" => SORT_DESC],
            'label' => 'Trades Count',
        ];
        $dataProvider->sort->attributes['tradesTotal'] = [
            'asc' => ["tradesTotal" => SORT_ASC],
            'desc' => ["tradesTotal" => SORT_DESC],
            'label' => 'Trades Total',
        ];
        $dataProvider->sort->attributes['tradesAmount'] = [
            'asc' => ["tradesAmount" => SORT_ASC],
            'desc' => ["tradesAmount" => SORT_DESC],
            'label' => 'Trades Amount',
        ];
        $this->load($params);
        if (!$this->validate()) {
            return $dataProvider;
        }
        $query->andFilterWhere([
            'userid' => $this->userid,
        ]);
        $query->andFilterWhere(['like', 'username', $this->username])
            ->andFilterWhere(['like', 'truename', $this->truename])
            ->andFilterWhere(['like', 'mobile', $this->mobile])
        // 对结果集需要用having处理
        $query->having(['>', 'tradesCount', 0]);
        $query->andHaving(['>', 'tradesTotal', 0]);
        $query->andHaving(['>', 'tradesAmount', 0]);
        if($this->tradesCount){
            $query->andHaving(['tradesCount'=>$this->tradesCount]);
        }
        if($this->tradesTotal){
            $query->andHaving(['tradesTotal'=>$this->tradesTotal]);
        }
        if($this->tradesAmount){
            $this->tradesAmount = (double)$this->tradesAmount;
            $query->andHaving(['tradesAmount'=>$this->tradesAmount]);
        }
        if($this->amountStart){
            $this->amountStart = (double)$this->amountStart;
            $query->andHaving(['>=', 'tradesAmount', $this->amountStart]);
        }
        if($this->amountEnd){
            $this->amountEnd = (double)$this->amountEnd;
            $query->andHaving(['<=', 'tradesAmount', $this->amountEnd]);
        }
        return $dataProvider;
    }
}
在视图中添加需要的列
$columns = [
        [
            'class' => \kartik\grid\SerialColumn::className(),
        ],
        'userid',
        'username',
        'truename',
        'mobile',
        [
            'attribute'=>'tradesCount',
            'format'=>'integer',
            'hAlign'=>'right',
            'width'=>'100px',
            'pageSummary'=>true
        ],
        [
            'attribute'=>'tradesTotal',
            'format'=>'integer',
            'hAlign'=>'right',
            'width'=>'100px',
            'pageSummary'=>true
        ],
        [
            'attribute'=>'tradesAmount',
            'format'=>'integer',
            'hAlign'=>'right',
            'width'=>'100px',
            'pageSummary'=>true,
            'filter'=>Html::input('text', 'MembersSearch[amountStart]', $searchModel->amountStart, ['class'=>'form-control col-lg-6']).Html::input('text', 'MembersSearch[amountEnd]', $searchModel->amountEnd, ['class'=>'form-control col-lg-6']),
        ],
        [
            'class' => \kartik\grid\ActionColumn::className(),
        ],
]
结果预览
![]()
wodrow China
            注册时间:2015-04-09
最后登录:10小时前
在线时长:215小时30分
    最后登录:10小时前
在线时长:215小时30分
- 粉丝34
 - 金钱48065
 - 威望120
 - 积分51415
 
共 3 条评论
这样真的好吗,为了发个教程把你公司内部的数据都暴露了,要有数据安全意识啊
嗯嗯会注意的
"COUNT(".Trades::tableName().".itemid) AS tradesCount",
这里,提示报错,Getting unknown property,tradesCount
public $tradesCount;要放在AR里,放在search里不行