【问题标题】:Can I fake laravel eager loading using a join?我可以使用连接来伪造 laravel 急切加载吗?
【发布时间】:2017-01-20 19:37:39
【问题描述】:

我已经阅读了几篇关于为什么急切加载使用多个查询而不是加入 hereherehere 的帖子。但是,我有一种情况,我认为需要使用连接而不是急切加载。我将如何构造查询,以便我可以访问子对象,就好像它是一个通常急切加载的对象一样?

示例:获取住在某条街道上的人,并同时加载该地址。我不想加载所有人的地址,以防他住在很多地方;只是匹配查询的地方。使用即时加载和 whereHas 我必须复制查询,而且查询并不总是这么简单:

People::with(['address', function($query) use ($street_name){
  return $query->where('street_name', $street_name);
}])->whereHas('address', function($query) use ($street_name){
  return $query->where('street_name', $street_name);
})->get();

可能

People::query()->join('address', function($join){
  $join->on(...)
})->where('street_name', $street_name);

问题是我不能使用这个:

$person->address

有没有办法获取连接并对其进行按摩(使用选择?)使其看起来像是急切加载的?

【问题讨论】:

  • 这两个查询会返回不同的结果。如果一个人可以拥有超过 1 个地址,则您想在此处使用 eloquent 关系,或者如果一个人只能拥有 1 个地址(与此查询匹配),则加入。 Here 是解决您的人际关系问题的一个不错的(ish)解决方法。
  • 如果你加入你不能做$person->address->address_attribute但你可以直接做$person->address_attribute。连接表的属性将附加到$person

标签: laravel join eager-loading


【解决方案1】:

您可以执行以下操作:

People::join('addresses', 'addresses.people_id', '=', 'people.id')
->selectRaw('people.*')
->where('street_name', $street_name)
->with('addresses')
->get();

这使用连接和预加载。

通过单独的连接,您可以访问以下内容:

$person->street_address

【讨论】:

  • 理想情况下,我会将它放入一个对象中,这样我仍然可以像这样访问它:$person->address->street_address,但我想我可以编写某种属性获取器来查看地址是否加载。