【问题标题】:Nested relationship stops working after first result嵌套关系在第一个结果后停止工作
【发布时间】:2017-06-11 19:44:01
【问题描述】:

这是我目前的查询:

$messages = Message::select('messages.*')
    ->where('post_id', 1)
    ->where('parent_id', 0)
    ->with(['children' => function ($query)
    {
        $query->take(3);
    }])
    ->paginate(10);

这是我的Message.php 类中的children 关系:

public function children() {
    return $this->hasMany('App\Message', 'parent_id', 'id');
}

这是我想要得到的输出:

- Message 1
    - Message 1.1
    - Message 1.2
    - Message 1.3
- Message 2
    - Message 2.1
    - Message 2.2
    - Message 2.3
- Message 3
    - Message 3.1
    - Message 3.2
    - Message 3.3
- etc

但是,它返回的是这个:

- Message 1
    - Message 1.1
    - Message 1.2
    - Message 1.3
- Message 2
- Message 3
- etc

查询似乎只返回第一个结果的孩子,但之后没有其他结果。

我做错了什么?如何修复我的查询以获得我需要的结果?

【问题讨论】:

  • 看看这篇文章 - softonsofa.com/…
  • 我计划将来获取孩子们的孩子们的消息,据我所知,该教程并未涵盖这种情况。
  • 如果该信息包含在问题中会很有帮助。

标签: php laravel eloquent laravel-5.3


【解决方案1】:

首先,回答“我做错了什么?”这个问题,如果您按照 documentation 进行 Eloquent 预加载,您会看到您构建的查询转换为:

select * from messages

select * from children where id in (1, 2, 3, 4, 5, ...) limit 3

(请注意,children 表名是我编的,因为我不知道您使用什么名称。)

检索记录后,Eloquent 将使用您所要求的内容构建其对象:所有消息及其所有子级 - 限制为 3 行。这就是为什么您只为第一个Message 获取孩子。


现在,如果您想坚持使用即时加载,您可以简单地摆脱 with 方法中的闭包:

$messages = Message::select('messages.*')
    ->where('post_id', 1)
    ->where('parent_id', 0)
    ->with('children') /* the constraint is gone */
    ->paginate(10);

有了这个分页结果,您将可以访问 all Messagesall 他们各自的孩子。接下来,例如在控制器中,您可以通过过滤或手动将每个子组限制为 3 来修改结果。或者,您可以快速而肮脏地执行此操作,并直接在您的视图中使用带有 break 的循环。

但不要做的又快又脏。

【讨论】:

  • 如果一条消息有 10,000 个孩子,这个解决方案不会检索所有 10,000 个孩子吗?然后我必须过滤掉 9,997 才能得到 3?
  • 当然,你会得到所有的孩子,但你正在使用的受限with 也是如此 - 你仍然检索 所有 孩子,只是你限制了他们你得到它们之后。 “你”是指“MySQL”。
  • 如果是这样的话,这将对性能造成巨大影响。如果我将其过滤到 3,那么检索 10,000 个孩子对我来说没有意义。
  • 我同意。我给出的解决方案是一个基本的蓝图。它是否适合你,你决定。希望你能弄明白。
猜你喜欢
  • 1970-01-01
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-27
  • 2016-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多