Какие отношения между таблицами Laravel лучше использовать в данном случае?

Таблица Profiles:

id name:
1 Olga,
2 Marina,
3 Zina

Таблица Languages:

id title
1 Немецкий,
2 Русский

Как правильно реализовать связи между таблицами если в Profile нам нужно получить не просто язык Немецкий,Русский или оба вместе для каждого профиля но и уровень от 1-6?

Нужно ли создать таблицу Level и привязать к Languages или как правильнее?

В профиле выбирается язык и его уровень. Сохранять всё в одну или разные таблицы?

То есть с HTML кода что ниже при выборе к примеру 1 языка мы получаем Id profile, id Language и Level

Если создать таблицу такую ?

profile_id language_id level
1          2           5

@foreach(App\Language::all() as $language)
    <div class="form-group  language-block col-md-12 ">
        <div class="col-md-6">
            <input onchange="language_level(4860,'language');" id="language_{{$language->id}}" class="languages" type="checkbox" name="language[]" value="{{$language->id}}">
            <label class="lang-label" for="language_{{$language->id}}">{{$language->title}}</label>
        </div>

        <div class="lang-radio col-md-1">
          <input type="radio" id="" onchange="language_level(4860,'language');" name="lang-level-{{$language->id}}" value="1" checked="" disabled>
          <label for="">1</label>
       </div>
       <div class="lang-radio col-md-1">
          <input type="radio" id="" onchange="language_level(4860,'language');" name="lang-level-{{$language->id}}" value="2" disabled >
          <label for="">2</label>
       </div>
       <div class="lang-radio col-md-1">
          <input type="radio" id="" onchange="language_level(4860,'language');" name="lang-level-{{$language->id}}" value="3" disabled>
          <label for="">3</label>
       </div>
       <div class="lang-radio col-md-1">
          <input type="radio" id="" onchange="language_level(4860,'language');" name="lang-level-{{$language->id}}" value="4" disabled>
          <label for="">4</label>
       </div>
       <div class="lang-radio col-md-1">
          <input type="radio" id="" onchange="language_level(4860,'language');" name="lang-level-{{$language->id}}" value="5" disabled>
          <label for="">5</label>
       </div>
       <div class="lang-radio col-md-1">
          <input type="radio" id="" onchange="language_level(4860,'language');" name="lang-level-{{$language->id}}" value="6" disabled>
          <label for="">6</label>
       </div>

    </div>
@endforeach

Спасибо


Ответы (2 шт):

Автор решения: doox911

Я бы разделил на 5 таблицы:

  1. Profiles - непосредственно профиль пользователя;
  2. Languages - доступные языки в системе;
  3. Levels - доступные уровни;
  4. Language Levels - уровни знания языка;
  5. Profile Languages - взаимосвязь между пользователем языком и его уровнем.

введите сюда описание изображения

Модель Profile:

class Profile extends Model {

  /**
   * @return HasMany
   */
  public function profile_languages(): HasMany {
    return $this->hasMany(ProfileLanguage::class);
  }

  /**
   * @return HasManyThrough
   */
  public function languages(): HasManyThrough {
    return $this->HasManyThrough(LanguageLevel::class,ProfileLanguage::class,  'profile_id', 'id', 'id', 'language_level_id');
  }

}

Модель LanguageLevel

class LanguageLevel extends Model {

  /**
   * @return HasOne
   */
  public function language(): HasOne{
    return $this->HasOne(Language::class, 'id', 'language_id');
  }

  /**
   * @return HasOne
   */
  public function level(): HasOne{
    return $this->HasOne(Level::class, 'id', 'level_id');
  }

}

Пример выборки: App\Profile::with('languages.level')->find(1) и её результат:

введите сюда описание изображения

→ Ссылка
Автор решения: radar4ick

Если пользоваться стандартами Laravel, то здесь вырисовывается следующая схема:

Profiles -> Languages -> manyToMany
Languages -> Levels -> manyToMany (но это необязательная связь, при втором решении).

Тут соответственно напрашиваются уже 5 таблиц:

  1. profiles
  2. languages
  3. levels
  4. language_level поля id, language_id, level_id
  5. language_user (по алфавиту наименование) с полями profile_id, language_level_id

Но это, если следовать всем нормальным формам БД и соблюдать атомарность таблиц.

Есть и второй вариант с 4 таблицами:

  1. profiles
  2. languages
  3. levels
  4. language_user с полями profile_id, language_id, level_id

Но второй вариант подразумевает "хвостик" во всех запросах withPivotParams, иначе не будет браться level_id

Ну а так решать Вам)

→ Ссылка