如何在 Eloquent 中查询特定关系

Posted

技术标签:

【中文标题】如何在 Eloquent 中查询特定关系【英文标题】:How to query specific relation(s) in Eloquent 【发布时间】:2020-11-24 10:49:59 【问题描述】:

我有这样结构的数据库表(有点像国际会议论文集):

languages (id, abbr)

papers (id, title, fulltext, language_id)

keywords (id)
keyword_translations (id, label, keyword_id, language_id) // cointains language-specific tranlation of given keyword
paper_keywords (id, paper_id, keyword_id) //M:N relation between papers and keywords

usage (id)
usage_translations (id, label, usage_id, language_id)
paper_usage (id, paper_id, usage_id) //M:N relation between papers and usages

这描述了论文及其元数据。所需的 UI 应该是多种语言的,因此有“翻译表”。

在我的 Eloquent 模型中,我已经建立了所有简单的 M:N belonsToMany 关系,例如“所有使用此设备的论文”。模型如下所示:

class Paper extends Model

    public function keywords()
    
        return $this->belongsToMany('App\Keyword', 'paper_keyword');
    

    public function usages()
    
        return $this->belongsToMany('App\Usage', 'paper_usage');
    

class Keyword extends Model

    public function translations()
    
        return $this->hasMany('App\KeywordTranslation');
    

    public function papers()
    
        return $this->belongsToMany('App\Paper', 'paper_keyword');
    

……用法相同。

现在我需要查询由其 ID 给出的特定论文(或者可能是多篇论文)以及属于它的所有关键字和用法 - 但仅具有给定 language_id 的那些。 (这个language_id只涉及翻译(对于UI),论文可以有不同的language_id。一个典型的例子是我想看一篇斯洛伐克语或波兰语的论文,但是UI是捷克语,所以应该有捷克语关键字和其他元数据的标签)。

我知道我可以做到App\Paper::with(['usages.translations', 'keywords.translations'])->find(1605);,但这会带来所有翻译,而不仅仅是特定于语言的翻译。在纯 SQL 中,我会简单地使用一些别名连接所有表并查询 WHERE keyword_translations.language_id = 1,但在 Eloquent 中?

我想避免需要修改数据库的解决方案。

【问题讨论】:

您是否正在寻找带有orWhere() 子句的where() 【参考方案1】:

我认为您需要以下查询

$languageId = 'language_id';

$papers = App\Paper::with(['usages.translations', 'keywords.translations'])
        ->whereHas('usages.translations', function($query) use ($languageId) 
            $query->where('language_id', $languageId);
        )
        ->whereHas('keywords.translations', function($query) use ($languageId) 
            $query->where('language_id', $languageId);
        )
        ->get();

【讨论】:

不幸的是,这不起作用 - 它会获取所有语言突变。【参考方案2】:

听起来你需要的是一个嵌套查询,如下所示:

App\Paper::with(['usages.translations', 'keywords.translations'])
            ->where('usages.translations.language_id', 'your_id_goes_here')
            ->orWhere('keywords.translations.language_id', 'your_id_goes_here')
            ->get();

【讨论】:

谢谢,我试过了,但是我收到了Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'usages.translation s.language_id' in 'where clause' (SQL: select * from `papers` where `usages`.`translations`.`language_id` = 1 or `keywords` .`translations`.`language_id` = 1)'

以上是关于如何在 Eloquent 中查询特定关系的主要内容,如果未能解决你的问题,请参考以下文章