【问题标题】:Proper way of finding Articles that share a Tag in many-to-many relation on Laravel's Eloquent在 Laravel 的 Eloquent 上查找以多对多关系共享标签的文章的正确方法
【发布时间】:2019-10-22 10:15:31
【问题描述】:

我有三个表,一个articles表,一个tags表,还有一个叫做article_tags的中间数据透视表,它只包含一个article_id和tag_id,形成了多对多的关系。

我想写一个函数来接收一篇文章,并返回一个集合或查询所有与接收到的文章共享至少一个标签的文章,在尝试了一堆不同的解决方案之后,我有这个:

public function scopeRelated($query, Article $article)
{
    return $query->whereHas('tags', function ($query) use ($article) {
        // I've tried a bunch of different lines, like just $article->tags
        $query->whereIn('tags', $article->tags->pluck('id'));
    });
}

这会返回一个错误:

使用消息“SQLSTATE[42S22] 照亮/数据库/查询异常: 未找到列:1054 'where 子句'中的未知列 'tags'(SQL: select * from articles where exists (select * from tags inner join article_tag on tags.id = article_tag.tag_id 在哪里 articles.id = article_tag.article_idtags 在 (1, 6, 4)))'

显然,Eloquent 正在尝试将标签与 Articles 表中不存在的“标签”列进行匹配。 问我想要什么的正确方式是什么?

【问题讨论】:

    标签: php laravel laravel-5 eloquent


    【解决方案1】:

    'tags' 列替换为'tags.id'。另外,如果$article 对象没有加载标签关系,我建议$article->tags()->pluck('id'),因为这样 eloquent 只会查询文章 id。

    Aken Roberts 是对的,您可能希望从结果中排除 $article。我假设带有文章的表格称为articles

    所以查询看起来像这样:

        return $query->whereHas('tags', function ($query) use ($article) {
            $query->whereIn('tags.id', $article->tags()->pluck('id'));
        })->where('articles.id', '<>', $article->id);
    

    【讨论】:

    • 这会产生错误:Illuminate/Database/QueryException with message 'SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in field list is ambiguous (SQL: select id from @987654330) @inner join article_tag on tags.id = article_tag.tag_id where article_tag.article_id = 1)'
    • 对,应该是'tags.id',这样mysql就知道id指的是哪个表了。编辑了我的答案。
    【解决方案2】:

    使用tag_id 对子查询进行超特定:

    return $query->whereHas('tags', function ($query) use ($article) {
        $query->whereIn('tag_id', $article->tags->pluck('id'));
    });
    

    'id' 正如另一个答案中所建议的那样,在 Laravel 5.8 和 MySQL 5.7 中对我有用。也许启用了某种严格模式,或者当您不需要时,您的id 表中确实有一个id 列。

    另外,不要忘记将原始文章从相关结果中排除! :)

    $query
        ->whereHas('tags', function ($query) use ($article) {
            $query->whereIn('tag_id', $article->tags->pluck('id'));
        })
        ->where('id', '<>', $article->id);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-15
      • 2022-01-12
      • 2013-05-15
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      • 2019-06-13
      • 2021-10-04
      相关资源
      最近更新 更多