You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2 GridView如何仅显示当前用户所属仓库的预订记录?

如何在Yii的ReservationsSearchModel中筛选用户所属仓库的预订记录?

先看你的数据库结构:
database model

你的需求很明确:用户只能查看自己所属仓库的预订记录,包括无user_id的公开预订,而且你已经搞定了单条记录的查看、删除、更新权限校验,但SearchModel的筛选逻辑一直没生效对吧?

先说说你现有代码的问题

你直接把ActiveQuery对象(比如$reservation_id)赋值给了id的筛选条件,Yii根本没法解析这种格式——它需要的是具体的ID值或数组,而不是一个查询对象;同时你也没用到in条件来匹配多个可能的预订ID,这就导致筛选完全没起作用。

下面给你两种可行的修正方案,你可以根据业务场景选择:

方案一:子查询获取ID数组再筛选(逻辑直观)

这种方式步骤清晰,容易理解:

public function search($params)
{
    $query = Reservation::find();

    // 1. 获取当前用户关联的所有仓库ID
    $userWarehouseIds = User_Has_Warehouse::find()
        ->select('warehouse_id')
        ->where(['user_id' => Yii::$app->user->id])
        ->column(); // 用column()直接拿到ID数组

    // 2. 获取这些仓库对应的冷冻柜类型ID
    $freezerTypeIds = Freezer_type::find()
        ->select('id')
        ->where(['warehouse_id' => $userWarehouseIds])
        ->column();

    // 3. 获取关联的预订ID
    $relatedReservationIds = Reservation_freezer_type::find()
        ->select('reservation_id')
        ->where(['freezer_type_id' => $freezerTypeIds])
        ->column();

    // 4. 用in条件筛选预订ID
    if (!empty($relatedReservationIds)) {
        $query->andFilterWhere(['in', 'id', $relatedReservationIds]);
    } else {
        // 如果用户无关联仓库,返回空结果(可根据业务调整)
        $query->andWhere('1=0');
    }

    // 加载并验证参数
    $this->load($params);
    if (!$this->validate()) {
        return new ActiveDataProvider(['query' => $query]);
    }

    // 原有筛选条件
    $query->andFilterWhere([
        'customer_id' => $this->customer_id,
        'user_id' => $this->user_id,
    ]);

    return new ActiveDataProvider([
        'query' => $query,
    ]);
}

方案二:关联查询直接筛选(性能更优)

这种方式只需要一次数据库查询,避免多次子查询,更符合Yii的关联设计思路。首先确保你的模型定义了正确的关联:

  • Reservation模型要有getReservationFreezerTypes()关联到Reservation_freezer_type
  • Reservation_freezer_type模型要有getFreezerType()关联到Freezer_type

然后修改SearchModel的search方法:

public function search($params)
{
    $query = Reservation::find();

    // 获取当前用户关联的仓库ID
    $userWarehouseIds = User_Has_Warehouse::find()
        ->select('warehouse_id')
        ->where(['user_id' => Yii::$app->user->id])
        ->column();

    if (!empty($userWarehouseIds)) {
        // 通过关联表筛选用户有权限的预订
        $query->joinWith([
            'reservationFreezerTypes' => function ($q) use ($userWarehouseIds) {
                $q->joinWith('freezerType')
                  ->where(['freezer_type.warehouse_id' => $userWarehouseIds]);
            }
        ]);
        // 去重,避免关联多条记录导致重复的预订结果
        $query->distinct();
    } else {
        $query->andWhere('1=0');
    }

    // 加载参数和原有筛选逻辑
    $this->load($params);
    if (!$this->validate()) {
        return new ActiveDataProvider(['query' => $query]);
    }

    $query->andFilterWhere([
        'customer_id' => $this->customer_id,
        'user_id' => $this->user_id,
    ]);

    return new ActiveDataProvider([
        'query' => $query,
    ]);
}

核心问题总结

  1. 不能直接把ActiveQuery对象当作条件值传递给andFilterWhere
  2. 多值筛选必须用in条件或者关联查询来实现

这样修改后,你的SearchModel就能正确返回当前用户所属仓库的所有预订记录,包括无user_id的公开预订啦!

内容的提问来源于stack exchange,提问作者user9831165

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:53:20