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 ...
随机推荐
- OpenLDAP备份和恢复
OpenLDAP中数据备份一般分为二种: 1)通过slapcat 指令进行备份 2)通过phpLDAPadmin控制台进行备份 备份方式1: 1)slapcat -v -l openldap-back ...
- 高可用Kubernetes集群-6. 部署kube-apiserver
八.部署kube-apiserver 接下来3章节是部署Kube-Master相关的服务,包含:kube-apiserver,kube-controller-manager,kube-schedule ...
- linux下各文件夹的结构说明及用途介绍(转载)
详细介绍文档 转载文章路径 /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录的基点,比如用户 ...
- c# 加载图片 正在被占用问题
问题情境:图片文件加载到pdf中,程序没有退出,再次加载该图片文件,提示被占用. 解决办法: 1.加载文件会锁定该文件,fromfile方法会导致占用内存较大,不使用该方法. FileStream f ...
- Iterable,Iterator和forEach
Iterable Interface Iterable<T> 方法: Iterator<T> iterator() Returns an iterator over a set ...
- Redis的sentinel机制(sentinel节点IP为:192.168.23.10) “哨兵”
万一主节点打击,主从模型将会停止工作,为了解决这个问题,Redis提供了一个sentinel(哨兵),以此来实现主从切换的功能,一旦主节点宕机了,sentinel将会在从节点中挑一个作为主节点.与zo ...
- "firstday"-软件工程
阅读以下文章 http://www.thea.cn/news/terminal/9/9389.html http://www.shzhidao.cn/system/2015/09/22/0102 ...
- 【第六周】关于beta测试组员评分标准的若干意见
组名: 新蜂 组长: 武志远 组员: 宫成荣 谢孝淼 杨柳 李峤 项目名称: java俄罗斯方块 评分规则:简单的才是坠吼的,本组不想搞个大新闻,所以奉行极简的评分方式.每一个人交给组长一个排名,假如 ...
- Mac 常用快捷键整理
Mac下常用的快捷键: Command+W 将当前窗口关闭(可以关闭Safari标签栏,很实用) Command+Option+M 将所有窗口最小化 Command+Q 关闭当前应用程序(相当于Doc ...
- wx import require的理解
服务器端的Node.js遵循CommonJS规范.核心思想是允许模块通过require 方法来同步加载所要依赖的其他模块,然后通过 exports或module.exports来导出需要暴露的接口. ...