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


Posted in PHP onOctober 18, 2018

首先看代码:

$userCoupons = UserCoupons::with(['coupon' => function($query) use($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 // 注意返回了coupons为空的数据
}

记录中有的coupon有记录,有的为空。想想也是,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` is null

如果第二条为空,主记录的关联字段就是NULL。

后来看到了Laravel关联的模型的has()方法,has()是基于存在的关联查询,下面我们用whereHas()(一样作用,只是更高级,方便写条件)

这里我们思想是把判断有没有优惠券数据也放在第一次查询逻辑中,所以才能实现筛选空记录。

加上whereHas()后的代码如下

$userCoupons = UserCoupons::whereHas('coupon', function($query) use($groupId){
  return $query->select('id', 'group_id', 'cover', 'group_number', 'group_cover')->where([
   'group_id' => $groupId,
  ]);
 })->with(['coupon' => function($query) use($groupId){
  return $query->select('id', 'group_id', 'cover', 'group_number', 'group_cover');
 }])-> // ...

看下最终的SQL:

select * from `youquan_user_coupons` where exists (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` is null) and (`status` = 1 and `user_id` = 1)

这里实际上是用exists()筛选存在的记录。然后走下一步的with()查询,因为此时都筛选一遍了,所以with可以去掉条件。

显然区分这两个的作用很重要,尤其是在列表中,不用特意去筛选为空的数据,而且好做分页。

总结

以上所述是小编给大家介绍的Laravel关联模型中过滤结果为空的结果集(has和with区别),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

PHP 相关文章推荐
第七节--类的静态成员
Nov 16 PHP
php 操作excel文件的方法小结
Dec 31 PHP
php自动加载的两种实现方法
Jun 21 PHP
php下统计用户在线时间的一种尝试
Aug 26 PHP
ThinkPHP3.1.3版本新特性概述
Jun 19 PHP
php设置页面超时时间解决方法
Sep 22 PHP
Yii实现文章列表置顶功能示例
Oct 18 PHP
php 截取utf-8格式的字符串实例代码
Oct 30 PHP
php 删除指定文件夹的实例讲解
Jul 25 PHP
原生JS实现Ajax通过POST方式与PHP进行交互的方法示例
May 12 PHP
详解PHP 二维数组排序保持键名不变
Mar 06 PHP
详解php中生成标准uuid(guid)的方法
Apr 28 PHP
PHP使用glob方法遍历文件夹下所有文件的实例
Oct 17 #PHP
php 读取文件夹下所有图片、文件的实例
Oct 17 #PHP
PHP使Laravel为JSON REST API返回自定义错误的问题
Oct 16 #PHP
实现PHP中session存储及删除变量
Oct 15 #PHP
PHP实现用session来实现记录用户登陆信息
Oct 15 #PHP
PHP中使用CURL发送get/post请求上传图片批处理功能
Oct 15 #PHP
深入理解 PHP7 中全新的 zval 容器和引用计数机制
Oct 15 #PHP
You might like
PHP中header和session_start前不能有输出原因分析
2013/01/11 PHP
thinkphp实现多语言功能(语言包)
2014/03/04 PHP
php中10个不同等级压缩优化图片操作示例
2016/11/14 PHP
PHP创建文件及写入数据(覆盖写入,追加写入)的方法详解
2019/02/15 PHP
Laravel统计一段时间间隔的数据方法
2019/10/09 PHP
PHP Beanstalkd消息队列的安装与使用方法实例详解
2020/02/21 PHP
IE FF OPERA都可用的弹出层实现代码
2009/09/29 Javascript
js判断页面中是否有指定控件的简单实例
2014/03/04 Javascript
js控制网页背景音乐播放与停止的方法
2015/02/06 Javascript
javascript框架设计之浏览器的嗅探和特征侦测
2015/06/23 Javascript
freemarker判断对象是否为空的方法
2015/08/13 Javascript
Bootstrap中datetimepicker使用小结
2016/12/28 Javascript
浅谈原生JS中的延迟脚本和异步脚本
2017/07/12 Javascript
关于JS与jQuery中的文档加载问题
2017/08/22 jQuery
Vue高版本中一些新特性的使用详解
2018/09/25 Javascript
浅谈layui里的上传控件问题
2019/09/26 Javascript
vue实现计算器功能
2020/02/22 Javascript
[01:43]倾听DOTA2英雄之声 魅惑魔女国服配音鉴赏
2013/06/06 DOTA
教大家玩转Python字符串处理的七种技巧
2017/03/31 Python
pandas.DataFrame 根据条件新建列并赋值的方法
2018/04/08 Python
Python日期时间模块datetime详解与Python 日期时间的比较,计算实例代码
2018/09/14 Python
python多进程读图提取特征存npy
2019/05/21 Python
Pyinstaller 打包exe教程及问题解决
2019/08/16 Python
Python 网络编程之UDP发送接收数据功能示例【基于socket套接字】
2019/10/11 Python
pandas实现将日期转换成timestamp
2019/12/07 Python
python:解析requests返回的response(json格式)说明
2020/04/30 Python
利用python3筛选excel中特定的行(行值满足某个条件/行值属于某个集合)
2020/09/04 Python
python多线程和多进程关系详解
2020/12/14 Python
Html5之svg可缩放矢量图形_动力节点Java学院整理
2017/07/17 HTML / CSS
屈臣氏官方旗舰店:亚洲享负盛名的保健及美妆零售商
2019/03/15 全球购物
CLR与IL分别是什么含义
2016/08/23 面试题
行风评议整改报告
2014/11/06 职场文书
篮球拉拉队口号
2015/12/25 职场文书
CSS3实现的3D隧道效果
2021/04/27 HTML / CSS
Java实现房屋出租系统详解
2021/10/05 Java/Android
CSS中实现动画效果-附案例
2022/02/28 HTML / CSS