【问题标题】:Laravel Collection::toArray() triggers extra database queriesLaravel Collection::toArray() 触发额外的数据库查询
【发布时间】:2020-03-14 10:52:42
【问题描述】:

让我们使用典型的帖子/标签示例。假设我想提取一些帖子的详细信息。我是一个聪明的开发者,想要限制数据库查询,所以我渴望将关系加载到标签。

<?php
class Post extends Model {
    public function tags() { return $this->belongsToMany(Tag::class); }
}

class Tag extends Model {
    public function posts() { return $this->belongsToMany(Post::class); }
}

$posts = Post::query()->with("tags")->where("title", "like", "foo%")->get();

到目前为止,一切都很好。我的数据库的查询日志显示了两个查询:

select * from `posts` where `title` like 'foo%' and `posts`.`deleted_at` is null;
select `tags`.*, `post_tag`.`post_id` as `pivot_post_id`, `post_tag`.`tag_id` as `pivot_tag_id`
    from `tags` inner join `post_tag` on `tags`.`id` = `post_tag`.`tag_id`
    where `post_tag`.`post_id` in (19, 880, 1462, 2712, 2713, 2717);

我现在可以毫无问题地处理帖子和标签。例如,我可以运行此代码而无需任何进一步的数据库查询:

foreach ($posts as $post) {
    echo $post->title . "(" . implode(",", $post->tags->pluck("name")->all()) . ")";
}

这告诉我关系中的数据已按预期保存到集合 $posts 中。


所以,我的问题是:为什么调用 $posts-&gt;toArray()$posts-&gt;toJson() 会导致 另一个 查询我的数据透视表中的 每个项目,拉已存储在集合中的相同数据?

select `tags`.*, `post_tag`.`post_id` as `pivot_post_id`, `post_tag`.`tag_id` as `pivot_tag_id`
from `tags` inner join `post_tag` on `tags`.`id` = `post_tag`.`tag_id`
where `post_tag`.`post_id` = 19 limit 1;
select `tags`.*, `post_tag`.`post_id` as `pivot_post_id`, `post_tag`.`tag_id` as `pivot_tag_id`
from `tags` inner join `post_tag` on `tags`.`id` = `post_tag`.`tag_id`
where `post_tag`.`post_id` = 880 limit 1;
...
select `tags`.*, `post_tag`.`post_id` as `pivot_post_id`, `post_tag`.`tag_id` as `pivot_tag_id`
from `tags` inner join `post_tag` on `tags`.`id` = `post_tag`.`tag_id`
where `post_tag`.`post_id` = 2717 limit 1;

有什么方法可以防止这些额外的查询发生吗?

【问题讨论】:

  • 您是否将数据“附加”到具有appends 属性的模型中?用访问器做什么?
  • 不,我并不总是需要额外的数据,所以不想强迫它。
  • 你能展示 Post 模型的其余部分吗
  • 在我的电脑上,它会导致 3 次查询(如果以前从未做过),一个限制为 1,一个选择 *,然后是枢轴查询
  • 啊,很高兴你找到它 :)

标签: php mysql laravel laravel-query-builder


【解决方案1】:

您可能有一个通过$appends 属性“附加”到模型数据的访问器。它可能是命中关系方法并导致查询,而不是使用关系的动态属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-24
    • 2013-01-10
    • 2014-01-21
    • 1970-01-01
    • 2018-04-22
    • 1970-01-01
    • 2014-06-04
    相关资源
    最近更新 更多