【问题标题】:Display parent id with many-to-many relationship显示具有多对多关系的父 ID
【发布时间】:2021-04-27 20:08:56
【问题描述】:

我有一个多对多的关系。我需要获取所有带有父 ID 的标签。例如,它可能看起来像这样:

[
   { article_id: 1, id: 1, name: "tag 1" },
   { article_id: 1, id, 2, name: "tag 2" },
   { article_id: 2, id: 1, name: "tag 1" }
]

看标签 1 是两篇文章的两倍。可能我可以在循环内循环,但它看起来并不专业。你能告诉我这个问题的最佳解决方案吗?

@编辑: 我创建了这段代码:

public function articles(){
    $article = [];
    $allArticles = Articles::all();
    foreach($allArticles as $key => $a){
        $obj = new \stdClass();
        foreach($a->tags as $t){
            $obj->article_id = $a->id;
            $obj->name = $t->name;
            array_push($article, $obj);
        }

    }


    return json_encode($article);
}

但它不像我想要的那样工作。它只为一篇文章显示一个标签,而不是全部。有什么想法吗?

【问题讨论】:

  • 但是,您的代码并未表明 Laravel 建议的多对多关系的任何迹象。

标签: php laravel


【解决方案1】:

不太了解您通过您提供的代码 sn-p 尝试实现的目标。但是,根据您问题的开头行,如果您想检索所有带有相关文章 ID 的标签,那么您可以尝试以下操作

$tags = Tag::with('articles')
    ->get()
    ->map(function($tag) {
        $tag->articleIds = $tag->articles->pluck('id');
        unset($tag->articles);
        return $tag;
    });

这会给你一个类似的输出

[
   { id: 1, name: "tag 1", articleIds: [1,2] },
   { id, 2, name: "tag 2", articleIds: [1] },
]

如果您想要其他方式,即获取带有关联标签的文章

$articles = Article::with('tags:id,name')
    ->get()
    ->map(function($article) {
        $object = new \StdClass;
        $object->article_id = $article->id;
        $object->tags = $article->tags;
        return $object;
    });

这会给你一个类似的输出

[
   { article_id: 1, tags: [{id: 1, name: "tag 1" }, {id, 2, name: "tag 2"}] },
   { article_id: 2, tags: [{id: 1, name: "tag 1" }]},
]

【讨论】:

    【解决方案2】:

    另一种方法是执行连接查询,它将根据 no 为每篇文章返回多行。分配的标签数

    $articles = DB::table('articles as a')
                ->select(['a.id','a.name','t.name as tag'])
                ->join('article_tags as at', 'a.id', '=', 'at.article_id')
                ->join('tags as t', 't.id', '=', 'at.tag_id')
                ->get();
    

    这样你就不需要额外的循环,也不会触发额外的查询(N+1)来获取相关标签。

    根据文档Relationship Methods Vs. Dynamic Properties

    动态属性是“延迟加载”,这意味着它们只会在您实际访问它们时加载它们的关系数据。正因为如此,开发人员经常使用预先加载来预加载他们知道在加载模型后会访问的关系。急切加载显着减少了加载模型关系所必须执行的 SQL 查询。

    如果您仍然想使用循环方法,那么至少使用像这样的急切加载

    $allArticles = Articles::with('tags')->all();
    

    但它仍然会触发多个查询。

    【讨论】:

    • 它一直只显示一个标签和一篇文章。我尝试了我的方法(使用 ::with('tags'))和你的方法。
    • @Fartuch2332 尝试过使用联合查询的方法,如果文章分配了多个标签,它应该为您提供多条记录
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    相关资源
    最近更新 更多