laravel5.1 eloquent with 经过闭包筛选特定 field 得不到结果的问题

(图片有点大,可右键新tab查看)php

 

User模型laravel

class User extends Model
{
    public function profile()
    {
        return $this->hasMany(UserProfile::class);
    }
}

  

使用with查询某个user及其的profilesql

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 框架的工做方式相关,咱们先看看下面的例子:ui

咱们使用 DB::listen 方法去记录相关的 sql 语句this

 

此次咱们不用find,用getspa

User::with('profile')->whereIn('id', [3, 4])
            ->get()->toArray()

  

咱们查看 log 能够发现有如下语句:debug

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 获得的仍是一个空集合。

(对于全部关联都有效哦)

相关文章
相关标签/搜索