laravel5.1 eloquent with 通过闭包筛选特定 field 得不到结果的问题
(图片有点大,可右键新tab查看)
User模型
class User extends Model
{
public function profile()
{
return $this->hasMany(UserProfile::class);
}
}
使用with查询某个user及其的profile
User::with(['profile' => function($query) {
$query->select(['id']);
}])->find(4)->toArray()
上面的用法中,我们会发现,即使数据库有记录,sql也记录了对应的查询语句,但是profile关联却是空的,
但是加上外键就可以得到正确结果了:
User::with(['profile' => function($query) {
$query->select(['id', 'user_id']);
}])->find(4)->toArray()
可以查找到正确的profile了。
这和 laravel 框架的工作方式相关,我们先看看下面的例子:
我们使用 DB::listen 方法去记录相关的 sql 语句
这次我们不用find,用get
User::with('profile')->whereIn('id', [3, 4])
->get()->toArray()
我们查看 log 可以发现有以下语句:
select * from `tb_user` where `id` in (?, ?) [3,4]
select * from `tb_user_profile` where `tb_user_profile`.`user_id` in (?, ?) [3,4]
我们可以明显发现,laravel 对于 user 和 user_profile 是独立查询的,
也就是说会得到两个集合,一个是 User、一个是 UserProfile,
但是这并不是我们想要的结果,我们需要的结果是,只有一个 User 集合, 并且这个 User 集合里面有 UserProfile 关联。
但是结果就是这样,如果是你,你会怎么把这些数据关联起来呢?
对了,我们定义关联的时候不是定义了它们的关联方式么?
上面的 hasMany 方法默认第二第三个参数其实就是这两个集合建立关联的关键,第三个参数 user_id、第四个参数 id;
这样一来我们就可以通过比较 UserProfile 的 user_id 和 User 里面的 id,如果相等,则这个 UserProfile 是属于这个 User 的,我们就把该 UserProfile 放进 User 的 profile 关联中,最后就得到我们想要的结果了。
用xdebug证实一下我们的想法:



如我们所想的那样,图一的 match 方法,顾名思义就是匹配了,通过 user 模型集合和 profile 模型集合进行匹配。
图二,也证实了我们模型建立关联需要通过关联中外键的值得想法。
图三,是通过获取 user 的 localkey,也就是 id 的值,来查找 $dictonary 中是否有对应的值,buildDictonary 方法会建立一个关联数组,key 是 user_id(外键)的值,值是关联的数据。这样一样,由于我们没有把 user_id 也select 出来,最后得到的 $dictonary 的结构并不是预期的那样:

其实我们本来是想要得到下面的这种:
[
3 => xxx(UserProfile对象) // 3 是关联的 user_id
]
但是我们得到的却是,所有的 UserProfile 都在一个嵌套的数组里面了,这样一来,下面的 getRelationValue 得到的结果自然就是空的了。
好了,总结一下,就是:laravel 先查询主要的数据(不带with),查询完了之后,取出其中的 id 列数组(不一定都是id啊,只是举个例子),将这个数组作为条件去查找关联,有多少个关联就会再去查找多少次,查找完关联之后通过得到的结果的主键和关联数据的外键比对,相等则建立关联。
总结:在关联筛选 field 的时候,也必须要把关联的外键写进去,否则,即使产生了正确的 sql 语句,但是它们建立不了关联,通过 $user->profile 得到的还是一个空集合。
(对于所有关联都有效哦)
laravel5.1 eloquent with 通过闭包筛选特定 field 得不到结果的问题的更多相关文章
- Swift - 使用闭包筛选过滤数据元素
通常筛选一个数组,通常会在代码的其它地方创建一个函数,然后为数组的每个元素调用它.但这样做会使代码分散在许多地方,不便于阅读.使用闭包就可以将相关代码片断放在一起,使结构逻辑更加清晰. 比如,筛选一个 ...
- pandas_读取Excel并筛选特定数据
# C:\Users\lenovo\Desktop\总结\Python # 读取 Excel 文件并进行筛选 import pandas as pd # 设置列对齐 pd.set_option(&qu ...
- python筛选特定文件的信息按照格式输出到txt
最近搞数据库,为了把图片文件的信息导入数据库表中,我开始研究python列出图片文件,其中发现因为IE临时文件里有非常多的不需要的图片,就需要筛选掉一些文件. 最终用python输出了所有需要的图片文 ...
- laravel5.8 eloquent
https://learnku.com/docs/laravel/5.8/eloquent/3931 示例1: $flights = App\Flight::all(); foreach ($flig ...
- awk 筛选特定长度的序列
awk '/^>/ {printf("\n%s\t",$0);next;} {printf("%s",$0);} END {printf("\n ...
- input="file" 浏览时只显示指定excel文件,筛选特定文件类型
<p>显示 .xls, .xlsx, .csv 文件...</p> <input type="file" accept=".csv, app ...
- nput="file" 浏览时只显示指定excel文件,筛选特定文件类型
<p>显示 .xls, .xlsx, .csv 文件...</p><input type="file" accept=".csv, appl ...
- Lucene in action 笔记 term vector——针对特定field建立的词频向量空间,不存!不会!影响搜索,其作用是告诉我们搜索结果是“如何”匹配的,用以提供高亮、计算相似度,在VSM模型中评分计算
摘自:http://makble.com/what-is-term-vector-in-lucene given a document, find all its terms and the posi ...
- MongoDB全文搜索——目前尚不支持针对特定field的搜索
> db.articles.createIndex( { subject: "text" } ) { "createdCollectionAutomatically ...
随机推荐
- Python数据挖掘——数据概述
Python数据挖掘——数据概述 数据集由数据对象组成: 数据的基本统计描述 中心趋势度量 均值 中位数 众数 中列数 数据集的最大值和最小值的平均 度量数据分布 极差 最大值与最小值的差 四分位数 ...
- PowerDesigne 建立概念数据模型
本文主要介绍PowerDesigner概念数据模型以及实体.属性创建. 一.新建概念数据模型1)选择File-->New,弹出如图所示对话框,选择CDM模型(即概念数据模型)建立模型. 2)完成 ...
- eBay:美国各州最受欢迎的产品品类
雨果网从美国媒体<商业内幕>8月26日的报道中获悉,电商巨头eBay近日发布了美国各州最受欢迎的产品品类.包括:加州人青睐女性高端配件,而新泽西 州的男人喜欢古龙香水.相比这些华丽配饰而言 ...
- Linux 150命令之 文件和目录操作命令 chattr lsattr find
chattr添加隐藏权限 lsattr查看隐藏权限 参数 a文件内容不能删除,只能追加 >> [root@mysql tmp]# chattr +a 1.txt [root@mysql t ...
- Android 对话框(Dialogs)
对话框是提示用户作出决定或输入额外信息的小窗口. 对话框不会填充屏幕,通常用于需要用户采取行动才能继续执行的模式事件. 1.对话框设计 如需了解有关如何设计对话框的信息(包括语言建议),请阅读对话框设 ...
- Friends and Cookies(思维)
Abood's birthday has come, and his n friends are aligned in a single line from 1 to n, waiting for t ...
- jquery新版本旧版本之间的坑
JQuery自1.6.1版本开始增加一些属性,使用时尽量使用这些新的属性,例如:selected.checked.在高版本中赋值时最好用prop,如果用attr就会出现赋值不成功的问题, 一般自定义属 ...
- 新手使用github过程记录
初次接触github,记录下我的使用过程.一开始确实有些懵,但好在网上这类的教程有很多,过程也很详细易懂,按照网上的教程走完全没问题,感谢无私分享辛苦整理的各位前辈们. 注册github账号 创建一个 ...
- ranch代码简述
最近要看一下erlang连接池,觉得ranch很不错. github上面有人写了ranch的代码阅读,可以看一下,链接在这里. 1. ranch可以同时监听多个端口,每个端口的连接信息可以单独配置. ...
- vsftpd:非常安全的ftp服务端程序
主程序:/usr/sbin/vsftpd 主配置文件:/etc/vsftpd/vsftpd.conf CentOS 6 /etc/rc.d/init.d/vsftpd chkconfig vsftp ...