Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
115 views
in Technique[技术] by (71.8m points)

php - Doctrine 2 and Many-to-many link table with an extra field

(Sorry for my incoherent question: I tried to answer some questions as I was writing this post, but here it is:)

I'm trying to create a database model with a many-to-many relationship inside a link table, but which also has a value per link, in this case a stock-keeping table. (this is a basic example for more problems I'm having, but I thought I'd just test it with this before I would continue).

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

I've used exportmwb to generate the two Entities Store and Product for this simple example, both are displayed below.

However, the problem now is that I can't figure out how to access the stock.amount value (signed int, as it can be negative) using Doctrine. Also, when I try to create the tables using doctrine's orm:schema-tool:create function

the database layout as it is seen from HeidiSQL

This yielded only two Entities and three tables, one as a link table without values and two data tables, as many-to-many relationships aren't entities themselves so I can only have Product and Store as an entity.

So, logically, I tried changing my database model to have stock as a separate table with relationships to store and product. I also rewrote the fieldnames just to be able to exclude that as a source of the problem:

changed database layout

Then what I found was that I still didn't get a Stock entity... and the database itself didn't have an 'amount'-field.

I really needed to be able to bind these stores and products together in a stock table (among other things)... so just adding the stock on the product itself isn't an option.

root@hdev:/var/www/test/library# php doctrine.php orm:info
Found 2 mapped entities:
[OK]   EntityProduct
[OK]   EntityStore

And when I create the database, it still doesn't give me the right fields in the stock table:

the database layout as it is seen from HeidiSQL

So, looking up some things here, I found out that many-to-many connections aren't entities and thus cannot have values. So I tried changing it to a separate table with relationships to the others, but it still didn't work.

What am I doing wrong here?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A Many-To-Many association with additional values is not a Many-To-Many, but is indeed a new entity, since it now has an identifier (the two relations to the connected entities) and values.

That's also the reason why Many-To-Many associations are so rare: you tend to store additional properties in them, such as sorting, amount, etc.

What you probably need is something like following (I made both relations bidirectional, consider making at least one of them uni-directional):

Product:

namespace Entity;

use DoctrineORMMapping as ORM;

/** @ORMTable(name="product") @ORMEntity() */
class Product
{
    /** @ORMId() @ORMColumn(type="integer") */
    protected $id;

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

    /** @ORMOneToMany(targetEntity="EntityStock", mappedBy="product") */
    protected $stockProducts;
}

Store:

namespace Entity;

use DoctrineORMMapping as ORM;

/** @ORMTable(name="store") @ORMEntity() */
class Store
{
    /** @ORMId() @ORMColumn(type="integer") */
    protected $id;

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

    /** @ORMOneToMany(targetEntity="EntityStock", mappedBy="store") */
    protected $stockProducts;
}

Stock:

namespace Entity;

use DoctrineORMMapping as ORM;

/** @ORMTable(name="stock") @ORMEntity() */
class Stock
{
    /** ORMColumn(type="integer") */
    protected $amount;

    /** 
     * @ORMId()
     * @ORMManyToOne(targetEntity="EntityStore", inversedBy="stockProducts") 
     * @ORMJoinColumn(name="store_id", referencedColumnName="id", nullable=false) 
     */
    protected $store;

    /** 
     * @ORMId()
     * @ORMManyToOne(targetEntity="EntityProduct", inversedBy="stockProducts") 
     * @ORMJoinColumn(name="product_id", referencedColumnName="id", nullable=false) 
     */
    protected $product;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...