Yii2 GridView如何仅显示当前用户所属仓库的预订记录?
如何在Yii的ReservationsSearchModel中筛选用户所属仓库的预订记录?
先看你的数据库结构:
你的需求很明确:用户只能查看自己所属仓库的预订记录,包括无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_typeReservation_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, ]); }
核心问题总结
- 不能直接把ActiveQuery对象当作条件值传递给
andFilterWhere - 多值筛选必须用
in条件或者关联查询来实现
这样修改后,你的SearchModel就能正确返回当前用户所属仓库的所有预订记录,包括无user_id的公开预订啦!
内容的提问来源于stack exchange,提问作者user9831165
相关产品推荐
相关产品推荐

