1

I'm trying to setup the relation between 'Products' and 'Merchants' through a linking table 'MerchantProduct' where I can store/override additional information. So the primary key consists of a combined key. I've tried to simplify the amount of fields per Entity to enhance the readability. The three Entities already worked fine before I tried to add the relations in YML, but I would like to go 'all the way' with Doctrine.

The error I get is:

[Doctrine\ORM\ORMException]
Column name id referenced for relation from BLAAT\Bundle\AdminBundle\Entity\Core\Product towards BLAAT\Bundle\AdminBundle\Entity\Core\MerchantProduct does not exist.

I'm not really sure why I get this error and don't know how to solve it. I'm afraid it has to do with the combined primary key.

Linking-entity with extra override information

BLAAT\Bundle\AdminBundle\Entity\Core\MerchantProduct:
    type: entity
    table: MerchantProduct
    repositoryClass: BLAAT\Bundle\AdminBundle\Entity\Core\MerchantProductRepository
    id:
        merchantId:
            type: integer
            column: merchant_id
        productId:
            type: string
            length: 255
            column: product_id

    fields:
        inStock:
            type: boolean
            column: in_stock
            nullable: TRUE
        productPrice:
            type: float
            column: product_price
            nullable: TRUE
        productDescription:
            type: text
            column: product_description
            nullable: TRUE

    oneToMany:
        products:
            targetEntity: Product
            mappedBy: product_id

    oneToMany:
        outlets:
            targetEntity: Merchant
            mappedBy: merchant_id

    lifecycleCallbacks: {  }

Product-entity

BLAAT\Bundle\AdminBundle\Entity\Core\Product:
    type: entity
    table: Product
    repositoryClass: BLAAT\Bundle\AdminBundle\Entity\Core\ProductRepository
    id:
        id:
            type: string
            length: 255
            id: true
            generator:
                strategy: NONE
    fields:
        title:
            type: string
            length: 255
        defaultDescription:
            type: text
            column: default_description
            nullable: TRUE
        defaultPrice:
            type: float
            column: default_price
            nullable: TRUE

    manyToOne:
        sellers:
            targetEntity: MerchantProduct
            inversedBy: products
            joinColumn:
                name: product_id
                referencedColumnName: id

    lifecycleCallbacks: {  }

Merchant-entity

BLAAT\Bundle\AdminBundle\Entity\Core\Merchant:
    type: entity
    table: null
    repositoryClass: BLAAT\Bundle\AdminBundle\Entity\Core\MerchantRepository
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    fields:
        title:
            type: string
            length: 255
        address:
            type: string
            length: 255

    manyToOne:
        stock:
            targetEntity: MerchantProduct
            inversedBy: outlets
            joinColumn:
                name: merchant_id
                referencedColumnName: id

    lifecycleCallbacks: {  }
Hanneman
  • 13
  • 2
  • Alternatively, maybe a many-to-many relation may work better: http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#many-to-many-bidirectional . This allows you to specify a join-table; like the one you created. – Herbert Aug 06 '14 at 08:50
  • Possibly you also may need to explicitely specify a "column: id" in the id's of Product and Merchant. – Herbert Aug 06 '14 at 09:02

1 Answers1

0

I think the mappedBys in MerchantProduct should be sellers and stock and that the referencedColumnNames should be productId and merchantId (or possibly product_id and merchant_id -- I haven't tested it, but something that exists in MerchantProduct, in any case).

It's the latter that seems to cause the error, because there is no column id: it should be productId.

To deal with a compound primary key, I think you need to use multiple JoinColumns to define the manyToOne relation in Merchant and Product. If I'm reading the documentation correctly, you can combine multiple JoinColumns under JoinColumns.

So:

manyToOne:
    stock:
        targetEntity: MerchantProduct
        inversedBy: outlets
        joinColumns:
            joinColumn:
                name: merchant_id
                referencedColumnName: merchantId
            joinColumn:
                name: product_id
                referencedColumnName: productId
towr
  • 4,147
  • 3
  • 20
  • 30
  • Why would you need both join-columns? Only the MerchantProduct.merchant_id is pointing to the Merchant, right? I think in this relation it is more 'coincidence' that we have a composite primary key, since the only primary key of interest is Merchant.id to which is only referenced via MerchantProduct.merchant_id. – Herbert Aug 06 '14 at 09:16
  • I think the ORM is going to have issues with trying to identify entities with only half their identity. But I haven't tried. – towr Aug 06 '14 at 09:26
  • I would not know either, but how would doctrine match Merchant.id against both MerchantProduct.merchant_id and MerchantProduct.product_id ? How would it know which one to pick? – Herbert Aug 06 '14 at 10:25
  • Doctrine adds columns to make the association. I think you'll get a `Merchant.merchant_id` and `Merchant.product_id` to match against the `MerchantProduct`. I don't remember if you can easily avoid creating that duplicate `merchant_id` column (it might be as easy as just using `id`, or Doctrine might make a fuss). – towr Aug 06 '14 at 10:54