使用中间表来定义一对一关系以避免外键循环的雄辩方式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用中间表来定义一对一关系以避免外键循环的雄辩方式相关的知识,希望对你有一定的参考价值。

Laravel新秀。我有标题评论。一个标题可以有很多评论,一个评论属于一个标题。

到目前为止,我的表看起来并不奇怪,如下所示:

titles:
  - id (pk)
  ...

reviews:
  - id (pk)
  - title_id (fk)
  ...

现在,我希望标题具有零或一个(所谓的)热门评论。

我的第一个直觉是向top_review_id表添加可为空的titles列,但我想避免外键循环。因此,我创建了名为top_reviews的第三个表,如下所示:

top_reviews:
  - id
  - title_id (fk, unique)
  - review_id (fk, unique)

这样一来,一个标题最多可以具有一个最高评价,而一个评价不能成为多个标题的最高评价。 (我确实意识到,仍然有可能有一个顶级评论条目,其中该评论实际上属于另一个标题,但这没关系。)

我的问题是,如何理想地使用雄辩的ORM关系并遵循框架的最佳实践,在Laravel(7.x)中将其整洁地连接起来?

到目前为止,我已经知道了:

class Title extends Model {
    public function reviews() { return $this->hasMany(Review::class); }
    public function topReview() { /* ??? */ }
}

class Review extends Model {
    public function title() { return $this->belongsTo(Title::class); }
}

我考虑了以下内容:

  • 我可以手动构建类似return Review::find(DB::table('top_reviews')->select('review_id')->where('title_id', $this->id)->get());的丑陋外观,但我怀疑对于这些琐碎的关系,还有一种更好的Laravelesque方法。

  • 简单地使用hasOne()似乎也不是解决方案,因为它将采用不同的表名(即reviews而不是top_reviews),并且无法指定自定义表。

  • 定义模型TopReview似乎很笨拙,但这也许是我最好的选择。我想这将使我可以将topReview()定义为hasOneThrough(Review, TopReview)

如果我走错路,请随时纠正我。

谢谢。

答案

与belongsToMany关系

class Title extends Model
{
    public function reviews()
    {
        return $this->hasMany(Review::class);
    }

    public function topReview()
    {
        return $this->belongsToMany(Review::class, 'top_reviews', 'title_id', 'review_id');
    }
}

无论如何,您都可以跳过该top_reviews表,而只需将top_review_id保存到您的titles表中,我认为这样更有效

另一答案

取决于您的要求您只有一个热门评论,所以我认为您应该拥有一个贯穿,但是如果您想在一个标题上拥有多名顶级评论者,则应该使用“多对多”。

top_reviews:
  - id
  - review_id (fk, unique)
class Title extends Model {
    public function topReview() { 
        return $this->hasOneThrough(TopReview::Class, Review::class);
    }

}
top_reviews:
  - id
  - title_id (fk, unique)
  - review_id (fk, unique)
class Title extends Model
{
    public function topReview()
    {
        return $this->belongsToMany(Review::class, 'top_reviews', 'title_id', 'review_id');
    }
}

但是如上所述。我想我会用一通。

以上是关于使用中间表来定义一对一关系以避免外键循环的雄辩方式的主要内容,如果未能解决你的问题,请参考以下文章

JPA的一对多,多对多用法

JPA一对多单向

关于JPA一对一,一对多(多对一),多对多的详解

Laravel 5.6 |雄辩的一对多关系

Laravel 雄辩的一对多关系

Jpa之关联对象(单向多对多)