Таблица ссылок Doctrine 2 и Many-to-many с дополнительным полем

(Извините за мой непоследовательный вопрос: я пытался ответить на некоторые вопросы, когда писал этот пост, но вот он:)

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

Database model for a basic multi-store, multi-product store-keeping system

Я использовал exportmwb для создания двух объектов Store and Product для этого простого примера, оба они отображаются ниже.

Однако теперь проблема заключается в том, что я не могу понять, как получить доступ к значению shareount (подписанное int, поскольку оно может быть отрицательным) с использованием Doctrine. Кроме того, когда я пытаюсь создать таблицы с помощью doctrine orm: schema-tool: create function

the database layout as it is seen from HeidiSQL

Это дало только две сущности и три таблицы: одну как таблицу ссылок без значений и две таблицы данных, поскольку отношения "многие ко многим" не являются сущностями, поэтому я могу иметь только Продукт и Хранить как сущность.

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

changed database layout

Тогда я обнаружил, что я все еще не получил объект Stock... и сама база данных не имела поля "amount".

Мне действительно нужно было объединить эти магазины и продукты вместе в таблице акций (среди прочего)... так что просто добавление запаса на самом продукте не является вариантом.

[email protected]:/var/www/test/library# php doctrine.php orm:info
Found 2 mapped entities:
[OK]   Entity\Product
[OK]   Entity\Store

И когда я создаю базу данных, она все равно не дает мне правильные поля в таблице запаса:

the database layout as it is seen from HeidiSQL

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

Что я здесь делаю неправильно?

Ответ 1

Связь "многие-ко-многим" с дополнительными значениями не является "много-ко-многим", но действительно является новой сущностью, поскольку теперь она имеет идентификатор (два отношения к связанным объектам) и значения.

Это также причина, по которой ассоциации Many-to-Many настолько редки: вы склонны хранить в них дополнительные свойства, такие как sorting, amount и т.д.

То, что вам, вероятно, нужно, это следующее: я сделал оба отношения двунаправленными, считаю, что хотя бы одно из них однонаправлено):

Продукт:

namespace Entity;

use Doctrine\ORM\Mapping as ORM;

/** @ORM\Table(name="product") @ORM\Entity() */
class Product
{
    /** @ORM\Id() @ORM\Column(type="integer") */
    protected $id;

    /** ORM\Column(name="product_name", type="string", length=50, nullable=false) */
    protected $name;

    /** @ORM\OneToMany(targetEntity="Entity\Stock", mappedBy="product") */
    protected $stockProducts;
}

Store:

namespace Entity;

use Doctrine\ORM\Mapping as ORM;

/** @ORM\Table(name="store") @ORM\Entity() */
class Store
{
    /** @ORM\Id() @ORM\Column(type="integer") */
    protected $id;

    /** ORM\Column(name="store_name", type="string", length=50, nullable=false) */
    protected $name;

    /** @ORM\OneToMany(targetEntity="Entity\Stock", mappedBy="store") */
    protected $stockProducts;
}

Наличие на складе:

namespace Entity;

use Doctrine\ORM\Mapping as ORM;

/** @ORM\Table(name="stock") @ORM\Entity() */
class Stock
{
    /** ORM\Column(type="integer") */
    protected $amount;

    /** 
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="Entity\Store", inversedBy="stockProducts") 
     * @ORM\JoinColumn(name="store_id", referencedColumnName="id", nullable=false) 
     */
    protected $store;

    /** 
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="Entity\Product", inversedBy="stockProducts") 
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id", nullable=false) 
     */
    protected $product;
}

Ответ 2

Doctrine обрабатывает отношения "многие-ко-многим" просто.

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

Ваша средняя (стоковая) таблица, так как она содержит больше, чем product_id и store_id, нуждается в ее собственной сущности для моделирования дополнительных данных.

Итак, вы действительно хотите три класса сущности:

  • Продукт
  • StockLevel
  • Магазин

и две ассоциации:

  • Продукт oneToMany StockLevel
  • Сохранить однозначное StockLevel