Лучшие практики с идентификаторами таблиц "многие ко многим" - PullRequest
0 голосов
/ 20 октября 2018

У меня есть некоторые сомнения по поводу идентификаторов таблиц «многие ко многим» (первичный ключ).Согласно документации Laravel, отношение «многие ко многим» состоит из двух моделей и трех таблиц.Каждая модель имеет свою соответствующую таблицу, а промежуточная таблица имеет следующие поля:

  • Автоинкрементный идентификатор
  • table1_id
  • table2_id
  • other_attributes...

Пока все хорошо.Я уже много использовал его, получая доступ к полям с помощью помощника 'pivot' и обновляя их с помощью 'updateExistingPivot' и т. Д.

У меня есть вопрос, стоит ли использовать преимущества идентификаторапромежуточная таблица, такая как FK из атрибутов других таблиц.

ПРИМЕР:

В моем приложении у меня есть следующие модели:

  • Машина
  • Product
  • Ограничение

И эти четыре таблицы:

  • машины (id, имя, ...) [Machine]
  • products (id, name, ...) [Product]
  • machine_products (id, machine_id [FK], product_id [FK], цена) [без модели]
  • ограничения (id, machine_product_id [FK], день, begin_hour, end_hour) [Ограничение]

Для конкретной машины и продукта существует N ограничений.Одно ограничение относится к одной конкретной Машине и Продукту.

Как видите, я использовал автоинкрементный идентификатор (первичный ключ промежуточной таблицы), чтобы связать ограничения.Но в этом случае работать с Eloquent немного странно, например, получить доступ к Restriction из Machine / Product или наоборот не так просто:

Restriction::where('machine_product_id', Machine::find(1)->products()->first()->pivot->id );

Если я получу Product илиMachine из данного Restriction, мне нужно было бы найти 'machine_id' и 'product_id' из строки с machine_product_id имеющегося у меня Ограничения.

Я не знаю, еслииз соображений практичности и функциональности при работе с Eloquent было бы лучше сделать две таблицы «многие ко многим» с machine_id and product_id, одну с price (machine_products), а другую с day, begin_hour, end_hour (restrictions).Первая таблица будет от 1 до 1 (machine_products), а другая от 1 до N (ограничения).Я имею в виду:

  • machine_products будет иметь только одну цену, учитывая конкретный machine_id и product_id.
  • restrictions будет иметь N строк набора, состоящего из дня, begin_hour, end_hour, учитывая конкретные machine_id и product_id.

Или было бы лучше, если бы я сделал модель под названием MachineProduct?Я не знаю ...

Не могли бы вы сказать мне или порекомендовать лучший способ решить эту дилемму?Уже вносите изменения в таблицы, модели или что-то еще.

Спасибо.

1 Ответ

0 голосов
/ 20 октября 2018

Если бы вы применяли строгий дизайн отношений сущностей только к вашим машинам и продукту , ваша промежуточная таблица будет иметь только два столбца.

 machine_id  INT PK  FK to machine.id
 product_it  INT PK  FK to product.id

Это реализует отношение Machine :: many-to-many :: Product.

Эта промежуточная таблица будет иметь составной первичный ключ.Уникальность первичного ключа будет диктовать, что каждая Машина может иметь только одно отношение с каждым Продуктом.Создайте отношение, вставив строку, и разорвите ее, удалив эту строку.

Но в вашем реальном приложении есть еще две вещи , цена и ограничение.Похоже, что ваше приложение диктует, что цены связаны как с машинами, так и с продуктами.

Итак, нам нужен другой объект, чтобы четко описать вашу заявку.Давайте назовем это Работа .Каждое задание имеет атрибут price.Он использует одну машину, чтобы сделать один продукт.Следовательно, он имеет следующие отношения.

  Machine  :: many-to-one :: Job 
  Product  :: many-to-one :: Job

Ваша machines_products таблица, следовательно, не является чистой промежуточной таблицей «многие: многие».Вместо этого она называется таблицей заданий (или, как вы ее называете, таблицей MachineProduct).

Наконец, у вас есть сущность Ограничения с этим отношением

  Job :: one-to-many :: Restriction

Итак, чтобы прояснить вашу модель Eloquent реального мира, добавьте эту сущность Job (MachineProduct) в вашу модель.Вся модель выглядит так.(Интересно, что в основе этого лежит сущность Job / MachineProduct.)

 +-------------+     +------------+     +---------------+   
 |             |    /|            |\    |               |   
 |   Product   |-----|     Job    |-----|     Machine   |   
 |             |    \|            |/    |               |   
 +-------------+     +------------+     +---------------+   
                            |                                
                            |                               
                           /|\
                     +-------------+                        
                     |             |                        
                     | Restriction |                        
                     |             |                        
                     +-------------+                        

Pro tip : Лучше четко определить свои сущности и отношения, прежде чем приступить к созданию таблиц.

Совет для профессионалов : Схему базы данных, вероятно, будет проще понять, если вы будете избегать имен столбцов, таких как machine.id, и вместо этого будете использовать machine.machine_id.Таким образом, вы можете говорить что-то подобное в своих запросах

 FROM Job j JOIN Machine m ON j.machine_id = m.machine_id

вместо

 FROM Job j JOIN Machine m ON j.machine_id = m.id

и не должны удивляться, подождать, что это за id, и донне рискуйте сделать это по ошибке:

FROM Job j JOIN Product p ON j.machine_id = p.id  /* wrong */
...