当前位置: 首页 > 后端技术 > PHP

Laravel关联模型中,过滤结果为空结果集(has和with的区别)

时间:2023-03-29 19:24:36 PHP

先看代码:$userCoupons=UserCoupons::with(['coupon'=>function($query)使用($groupId){return$query->select('id','group_id','cover','group_number','group_cover')->where(['group_id'=>$groupId,]);}])//更多查询省略...数据结构为三张表用户优惠券表(user_coupons)、优惠券表(coupons)、商家表(corps)、团体优惠券表(group_coupons)(为了方便查看,最后一个去掉了两项)这里我本来打算用模型关联的方式,找出用户优惠券中属于给定组gourpId的所有数据(如果为空则不返回数据)。但是有些结果不是我想要的:array(20){["id"]=>int(6)["user_id"]=>int(1)["corp_id"]=>int(1)["coupon_id"]=>int(4)["obtain_time"]=>int(1539739569)["receive_time"]=>int(1539739569)["status"]=>int(1)["expires_time"]=>int(1540603569)["is_selling"]=>int(0)["from_id"]=>int(0)["sell_type"]=>int(0)["sell_time"]=>int(0)["sell_user_id"]=>int(0)["is_compose"]=>int(0)["group_cover"]=>string(0)""["is_delete"]=>int(0)["score"]=>int(100)["created_at"]=>NULL["updated_at"]=>NULL["coupon"]=>NULL//注意优惠券是空数据}记录中的优惠券有的有记录,有的是空的。想想也是,with不过是用sql的in()实现的所谓预加载而已。不管主要的user_coupons数据是什么都会被列出来。它将有两个sql查询,第一个检查主要数据,第二个检查关联。这里,第二个sql如下:select`id`,`group_id`,`cover`,`group_number`,`group_cover`from`youquan_coupons`where`youquan_coupons`.`id`in(1,2,3,4,5,7,8,9,10,11,13,14)and(`group_id`=1)and`youquan_coupons`.`deleted_at`为null如果第二个为空,主记录的关联字段为NULL.后来看到Laravel关联模型的has()方法。has()基于现有的关联查询。接下来,我们使用whereHas()(相同的功能,但更高级,更方便编写条件)。这里我们的思路是判断是否有优惠券数据也放在第一个查询逻辑中,这样可以过滤空记录。添加whereHas()后的代码如下','group_number','group_cover')->where(['group_id'=>$groupId,]);})->with(['coupon'=>function($query)use($groupId){返回$query->select('id','group_id','cover','group_number','group_cover');}])->//...看最后的SQL:select*from`youquan_user_coupons`whereexists(select`id`,`group_id`,`cover`,`group_number`,`group_cover`from`youquan_coupons`where`youquan_user_coupons`.`coupon_id`=`youquan_coupons`.`id`and(`group_ids`=1)and`youquan_coupons`.`deleted_at`isnull)and(`status`=1and`user_id`=1)这里其实是用exists()过滤已有的记录。然后进入下一步with()查询,因为此时已经过滤了,所以with可以去掉条件。显然,区分这两个角色是很重要的,尤其是在列表中,不需要过滤掉空数据,做分页也很容易。本文首发于Rootrl博客

猜你喜欢