(图片有点大,可右键新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 得不到结果的问题的更多相关文章

  1. Swift - 使用闭包筛选过滤数据元素

    通常筛选一个数组,通常会在代码的其它地方创建一个函数,然后为数组的每个元素调用它.但这样做会使代码分散在许多地方,不便于阅读.使用闭包就可以将相关代码片断放在一起,使结构逻辑更加清晰. 比如,筛选一个 ...

  2. pandas_读取Excel并筛选特定数据

    # C:\Users\lenovo\Desktop\总结\Python # 读取 Excel 文件并进行筛选 import pandas as pd # 设置列对齐 pd.set_option(&qu ...

  3. python筛选特定文件的信息按照格式输出到txt

    最近搞数据库,为了把图片文件的信息导入数据库表中,我开始研究python列出图片文件,其中发现因为IE临时文件里有非常多的不需要的图片,就需要筛选掉一些文件. 最终用python输出了所有需要的图片文 ...

  4. laravel5.8 eloquent

    https://learnku.com/docs/laravel/5.8/eloquent/3931 示例1: $flights = App\Flight::all(); foreach ($flig ...

  5. awk 筛选特定长度的序列

    awk '/^>/ {printf("\n%s\t",$0);next;} {printf("%s",$0);} END {printf("\n ...

  6. input="file" 浏览时只显示指定excel文件,筛选特定文件类型

    <p>显示 .xls, .xlsx, .csv 文件...</p> <input type="file" accept=".csv, app ...

  7. nput="file" 浏览时只显示指定excel文件,筛选特定文件类型

    <p>显示 .xls, .xlsx, .csv 文件...</p><input type="file" accept=".csv, appl ...

  8. 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 ...

  9. MongoDB全文搜索——目前尚不支持针对特定field的搜索

    > db.articles.createIndex( { subject: "text" } ) { "createdCollectionAutomatically ...

随机推荐

  1. 在Emacs 23里字体的调整(转自ChinaUnix.net)

    首先,在Emacs中,通过菜单Options --> Set Default Font,设置好你喜欢的字体. 然后,把光标放到你所在的字体上,用命令M-x describe-font来查看你当前 ...

  2. [leetcode-914-X of a Kind in a Deck of Cards]

    In a deck of cards, each card has an integer written on it. Return true if and only if you can choos ...

  3. Requests库与HTTP协议

    了解HTTP协议 请求与响应模式的协议: 用户提出对URL(用来定位网络中的资源位置)地址数据的操作请求,服务器给予相应. 无状态的应用层协议:两次请求之间不会互相影响. HTTP协议支持的请求种类: ...

  4. Xcode 6添加模板无效

    最近发现从Xcode 5拷贝来的模板在Xcode 6上是OK的,但是自己自定义的却不行,一直使用的是自定义的基类模板,最后发现原因是没有在 TemplateInfo.plist 中注册自定义的模板,注 ...

  5. iOS- Autolayout自动布局

    1.前言 •在iOS程序中,大部分视图控制器都包含了大量的代码用于设置UI布局,设置控件的水平或垂直位置,以确保组件在不同版本的iOS中都能得到合理的布局 •甚至有些程序员希望在不同的设备使用相同的视 ...

  6. RequestMappingHandlerMapping 详解

    我们先理简单梳理一个关系 关系梳理 spring ioc 是spring的核心,用来管理spring bean的生命周期 MVC 是一种使用 MVC(Model View Controller 模型- ...

  7. js中如何获取页面的Url,域名和端口号

    有时候通过获取上个页面的Url来做一个跳转,获取域名防止非正常访问 获取上一个页面的一个URL,这个URL一般做一个页面的跳转 window.location.href <script>w ...

  8. 两个float 怎么比较大小

    转自:http://blog.csdn.net/mydriverc2/article/details/49888947 float 类型不能比较相等或不等,但可以比较>,<,>=,& ...

  9. .netMVC Vue axios 获取数据

    网页 <link href="~/Content/css/bootstrap-theme.min.css" rel="stylesheet" /> ...

  10. 【.Net】C#获取Windows系统特殊文件夹的路径

    系统特殊文件夹是包含公共信息的文件夹,如“Program Files”.“Programs”.“System”或“Startup”.特殊文件夹在默认情况下由系统设置,或者由用户在安装 Windows ...