Doctrine2および追加フィールドを備えた多対多リンクテーブル


88

(私の一貫性のない質問については申し訳ありません:私はこの投稿を書いているときにいくつかの質問に答えようとしましたが、ここにあります:)

リンクテーブル内に多対多の関係を持つデータベースモデルを作成しようとしていますが、リンクごとの値(この場合は在庫管理テーブル)もあります。(これは私が抱えているより多くの問題の基本的な例ですが、続行する前にこれでテストしたいと思いました)。

基本的な複数店舗、複数商品の店舗保管システムのデータベースモデル

私が使用してきましたexportmwbをこの単純な例のために2つのエンティティストアや製品を生成するために、両方の下に表示されます。

ただし、現在の問題は、Doctrineを使用してstock.amount値(負の値になる可能性があるため、signed int)にアクセスする方法がわからないことです。また、doctrineのorm:schema-tool:create関数を使用してテーブルを作成しようとすると

HeidiSQLから見たデータベースレイアウト

多対多の関係はエンティティ自体ではないため、ProductとStoreのみをエンティティとして持つことができるため、これにより、2つのエンティティと3つのテーブル(1つは値のないリンクテーブル、2つのデータテーブル)のみが生成されました。

そこで、論理的には、データベースモデルを変更して、在庫をストアと製品の関係を持つ別個のテーブルとして持つようにしました。また、問題の原因として除外できるように、フィールド名を書き直しました。

データベースレイアウトの変更

それから私が見つけたのは、まだStockエンティティを取得していないことでした...そしてデータベース自体には「amount」フィールドがありませんでした。

私は本当にこれらの店舗と商品を在庫テーブルにまとめることができる必要がありました(とりわけ)...したがって、商品自体に在庫を追加することはオプションではありません。

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

また、データベースを作成しても、ストックテーブルに適切なフィールドが表示されません。

HeidiSQLから見たデータベースレイアウト

そこで、ここでいくつか調べてみると、多対多の接続はエンティティではないため、値を持つことができないことがわかりました。そこで、他のテーブルとの関係を持つ別のテーブルに変更しようとしましたが、それでも機能しませんでした。

私はここで何が間違っているのですか?


わかりました。Doctrineを使用して多対多の接続を確立することは不可能であり、これらの関係を防ぐようにアドバイスするコメントがいくつかあります。しかし、私が説明したような状況で本当に立ち往生している場合はどうなりますか。私の元の質問?私は、多対多の関係に完全に依存する、Magentoと互換性のあるデータベース全体を持っています。つまり、基本的に「Doctrine ORMは多対多を処理できないので、使用しないでください」と言われています。
Henry van Megen 2013年


3
私がこのように素晴らしい方法で疑問に思っていたことを正確に説明するためにあなたが行った努力のために私ができればあなたに+100を与えるでしょう:
TorstenRömer2014年

回答:


141

追加の値との多対多の関連付けは多対多ではありませんが、識別子(接続されたエンティティへの2つの関係)と値を持つようになったため、実際には新しいエンティティです。

あなたはそれらに追加のプロパティを格納する傾向がある、など:それはまた、多対多の関連はとても稀である理由だsortingamountなど

おそらく必要なのは次のようなものです(両方の関係を双方向にしました。少なくとも一方を単方向にすることを検討してください)。

製品:

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

お店:

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

わかりました。ゲッターとセッターをいくつか追加します。この設定では、値なしで主キーのみを起動して実行するためです:)
Henry van Megen 2013年

この設定を使用してからStock.store_idを使用してクエリを実行しようとすると、「Stockにはstore_idという名前のフィールドまたは関連付けがありません」というエラーが表示されます。列がデータベースに存在するため、これが見つかるはずです。
afilina 2013

@afilinaスキーマの生成中にデータベースは重要ではありません-DBALは(メモリ内の)DDLメタデータで列が見つからないため、例外をスローします
Ocramius 2013

@Ocramiusつまり、DBはメタデータから生成されたということです。Sそもそも列を生成できた場合は、クエリ中に列を見つけることができるはずです。私の問題の解決策は、Stock.storeを目的のIDと比較することでした。
afilina 2013

必要なものを100%使用すると、魅力のように機能します。店舗および商品ごとの金額を編集するために、フィールドセットを使用してフォームを作成する方法を知っていますか?
cwhisperer 2014年

17

Doctrineは多対多の関係をうまく処理します。

あなたが抱えている問題は、アソシエーションが「余分な」データを持つことができないため、単純なManyToManyアソシエーションを必要としないことです。

真ん中の(在庫)テーブルには、product_idとstore_id以外のものが含まれているため、その追加データをモデル化するために独自のエンティティが必要です。

したがって、実際には3つのクラスのエンティティが必要です。

  • 製品
  • 在庫量
  • お店

および2つの関連付け:

  • 製品oneToManyStockLevel
  • oneToManyStockLevelを保存します

1
ご回答ありがとうございます!テーブルのような「ストック」にフィールドを追加しました。ただし、Doctrineはまだこの「結合テーブル」を考慮せずphp app/console doctrine:mapping:import AppBundle yml、データベースからスキーマをインポートするために実行するときにスキップします。この追加のマッピングyamlファイルを生成したいと思います。誰かアイデアはありますか?:(
stphane 2015年

「接続」エンティティへのデータの書き込みを解決しないと答えます。これは問題だ。エンティティを宣言していません。フォームからデータが渡される例を誰かがサポートできますか(CollectionTypeフィールドにはEntityTypeフィールドが埋め込まれたフォームがあります)。埋め込みフォームからメインフォームにデータを渡せず、フィールドのコレクションを適切に保存できません
2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.