Красноречивый способ определения отношения один-к-одному с использованием промежуточной таблицы, чтобы избежать цикла внешнего ключа - PullRequest
0 голосов
/ 02 апреля 2020

Laravel ладья ie здесь. У меня есть заголовков и отзывов . Заголовок может иметь много отзывов, отзыв принадлежит заголовку.

Пока мои таблицы выглядят неудивительно следующим образом:

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)

Таким образом, заголовок гарантированно будет иметь не более одного верхнего обзора, и обзор не может быть лучшим для нескольких заголовков. (Я понимаю, что все еще возможно иметь топовую запись рецензии, где рецензия действительно принадлежит другому названию, но это нормально.)

Мой вопрос заключается в том, как правильно подключить это Laravel (7.x) в идеале использовать отношения Eloquent ORM и следовать передовым методикам фреймворка?

Пока у меня есть это:

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());, но я подозреваю, что есть ларелевский способ для этих тривиальных отношений.

  • Простое использование hasOne() также не представляется решением, поскольку оно предполагает другое имя таблицы (а именно reviews вместо top_reviews), и нет никакой возможности указать пользовательскую таблицу.

  • Определение модели TopReview кажется неуклюжим, но, возможно, это мой лучший выбор. Я полагаю, что это позволило бы мне определить topReview() как hasOneThrough(Review, TopReview).

Не стесняйтесь исправлять меня, если я на неправильном пути.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 02 апреля 2020

Зависит от вашего требования. Вы один только один из лучших обзоров, поэтому я думаю, что вы должны иметь One Through, но если вы хотите, чтобы у вас было несколько лучших рецензентов на одно название, вам следует использовать Many To Many.

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');
    }
}

но как вы описали выше. Я думаю, что я буду использовать один через.

0 голосов
/ 02 апреля 2020

С отношением ownToMany

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, и я думаю, что она более эффективна

...