DDC-2772: One class can be mapped to multiple discriminator values #3467

Open
opened 2026-01-22 14:20:26 +01:00 by admin · 7 comments
Owner

Originally created by @doctrinebot on GitHub (Nov 1, 2013).

Originally assigned to: @beberlei on GitHub.

Jira issue originally created by user mouyang:

I'm not sure if this is intentional or not, but this appears to a valid discriminator map. The problem I am running into is that it's impossible to create an instance of ClassB with a discriminator value "DiscB" (it's always "DiscC" - I'm assuming last one wins here).

<entity name="ClassB" ...>
  <discriminator-map>
    <discriminator-mapping value="DiscA" class="ClassA" />
    <discriminator-mapping value="DiscB" class="ClassB" />
    <discriminator-mapping value="DiscC" class="ClassB" />
  </discriminator-map>
</entity>

Eventhough DiscB and DiscC map to the same class, I do want to maintain some sort of logical separation in the database using the two discriminator values. That does not appear to be possible. I can provide more details about my data model, if necessary.

These are the possible solutions I can think of.

  1. Enforce a strict one-to-one relationship between value and class. This means I would have to modify my code to reflect this.
  2. (I know this has been rejected before, but I'm in favour of this solution.) Expose the discriminator field but validate it before committing to the database. I'm actually using the discriminator as part of a compound primary key, so this would be very helpful to me.
Originally created by @doctrinebot on GitHub (Nov 1, 2013). Originally assigned to: @beberlei on GitHub. Jira issue originally created by user mouyang: I'm not sure if this is intentional or not, but this appears to a valid discriminator map. The problem I am running into is that it's impossible to create an instance of ClassB with a discriminator value "DiscB" (it's always "DiscC" - I'm assuming last one wins here). ``` <entity name="ClassB" ...> <discriminator-map> <discriminator-mapping value="DiscA" class="ClassA" /> <discriminator-mapping value="DiscB" class="ClassB" /> <discriminator-mapping value="DiscC" class="ClassB" /> </discriminator-map> </entity> ``` Eventhough DiscB and DiscC map to the same class, I do want to maintain some sort of logical separation in the database using the two discriminator values. That does not appear to be possible. I can provide more details about my data model, if necessary. These are the possible solutions I can think of. 1. Enforce a strict one-to-one relationship between value and class. This means I would have to modify my code to reflect this. 2. (I know this has been rejected before, but I'm in favour of this solution.) Expose the discriminator field but validate it before committing to the database. I'm actually using the discriminator as part of a compound primary key, so this would be very helpful to me.
admin added the Bug label 2026-01-22 14:20:26 +01:00
Author
Owner

@guilhermeblanco commented on GitHub (Jan 3, 2017):

Our intended solution is 1. "Enforce a strict one-to-one relationship between value and class. This means I would have to modify my code to reflect this."

An enforcement should be added restricting people to map multiple discriminator values to a single class. This should be done at mapping level by checking count(array_unique($map)) === count($map) and adding a MappingException if it doesn't match.

@guilhermeblanco commented on GitHub (Jan 3, 2017): Our intended solution is 1. "Enforce a strict one-to-one relationship between value and class. This means I would have to modify my code to reflect this." An enforcement should be added restricting people to map multiple discriminator values to a single class. This should be done at mapping level by checking `count(array_unique($map)) === count($map)` and adding a MappingException if it doesn't match.
Author
Owner

@beberlei commented on GitHub (May 12, 2022):

This makes sense for ORM 3.0 but also requires a deprecation message to be thrown in 2.x

@beberlei commented on GitHub (May 12, 2022): This makes sense for ORM 3.0 but also requires a deprecation message to be thrown in 2.x
Author
Owner

@derrabus commented on GitHub (May 12, 2022):

Do you want to work on it? 🙃

@derrabus commented on GitHub (May 12, 2022): Do you want to work on it? 🙃
Author
Owner

@javijavo commented on GitHub (May 13, 2022):

Hello,
I would like to ask why is this not possible?
If I have a let's say two possible classes Mammals and Reptiles and I want to discriminate "cat", "dog" to Mammals and "turtle" to Reptile? How do we do it after this deprecation?

(The example is very basic but I have some entity that works thay way)

Thanks

@javijavo commented on GitHub (May 13, 2022): Hello, I would like to ask why is this not possible? If I have a let's say two possible classes Mammals and Reptiles and I want to discriminate "cat", "dog" to Mammals and "turtle" to Reptile? How do we do it after this deprecation? (The example is very basic but I have some entity that works thay way) Thanks
Author
Owner

@beberlei commented on GitHub (May 13, 2022):

@javijavo but there is no way to new Mamal() and have it stored as either dog or cat. Do you create these entities outside the ORM?

@beberlei commented on GitHub (May 13, 2022): @javijavo but there is no way to new Mamal() and have it stored as either dog or cat. Do you create these entities outside the ORM?
Author
Owner

@javijavo commented on GitHub (May 13, 2022):

I have a very old and huge legacy application progressively adating it to Doctrine and yes the data is already stored.

But I see the problem of having multiple values, didn't have in mind the "standard" scenario instead my ugly one.
Will look for another way to meet my requirements.

Thanks

@javijavo commented on GitHub (May 13, 2022): I have a very old and huge legacy application progressively adating it to Doctrine and yes the data is already stored. But I see the problem of having multiple values, didn't have in mind the "standard" scenario instead my ugly one. Will look for another way to meet my requirements. Thanks
Author
Owner

@oleg-andreyev commented on GitHub (Oct 1, 2025):

Having similar issue...

we have and ERP (Windows App) that we cannot control or change, but we need some sort of API and we need to have multiple values for same class

ORM\DiscriminatorMap([
        'I2SA' => ImportOfGoods::class,  // Receipt of goods after advance payment
        'I3SA' => ImportOfGoods::class,  // 3ES Receipt of goods from EU
        'I5SA' => ImportOfGoods::class,  // 51 Receipt of goods without VAT
        'I1SA' => ImportOfGoods::class,  // 2LV Receipt of goods
        'I9SA' => ImportOfGoods::class,  // Medical goods receipt
        'IPSA' => ImportOfGoods::class,  // Receipt after inventory
        'P1SA' => ImportOfGoods::class,  // Receipt of samples LV
        'IMSA' => ImportOfGoods::class,  // 3rd country Receipt of goods Imports
        'DBSA' => ImportOfGoods::class,  // Business trip for goods delivery
        'T1SA' => ImportOfGoods::class,  // EU Transport service receipt from EU
        'T2SA' => ImportOfGoods::class,  // Transport service receipt
...
        'R4AB' => SalesOfGoods::class,   // Goods sale after advance payment
        'ABAB' => SalesOfGoods::class,   // Write-off for business needs
        'E1AB' => SalesOfGoods::class,   // 4ES Goods sale EU 0%;VAT43(4)16.16.Dir2006/11
        'R1AB' => SalesOfGoods::class,   // 1LV Goods sale
        'E3AB' => SalesOfGoods::class,   // EU Goods sale EU 21%; VAT law art.28.1.
        'R9AB' => SalesOfGoods::class,   // Medical goods sale
        'ISAB' => SalesOfGoods::class,   // Write-off after inventory
...
        'M1AA' => InternalMovement::class, // Internal movement

        'V2AS' => ReturnToSupplier::class, // Goods return to supplier
        'V3AS' => ReturnToSupplier::class, // EU Goods return to EU; VAT law art.28.1.

        'V4BA' => CustomerReturn::class, // Goods return from customer current rate
        'V6BA' => CustomerReturn::class, // Goods return from EU 0% customer

        'OFSB' => PurchaseOffer::class, // Advance payment; 21%
        'EFSB' => PurchaseOffer::class, // OFFER PAYPER EU 0%;VAT law art.43. (4)


        'N0SB' => CreditNote::class, // Credit invoice EU 0%
        'K3SB' => CreditNote::class, // Credit invoice 3rd country 0%

        'Y1SB' => ProformaInvoice::class, // Avansa rēķins no piegādātāja LV ar PVN  21%
...
        'POAR' => ReservationOrRent::class,    // Reservation
        'PXPP' => InternalMovement::class,
    ])

and unfortunately for me... I get it why it impossible...

when doing new CreditNote() we don't know under which discriminatorValue to write N0SB or K3SB...

@oleg-andreyev commented on GitHub (Oct 1, 2025): Having similar issue... we have and ERP (Windows App) that we cannot control or change, but we need some sort of API and we need to have multiple values for same class ``` ORM\DiscriminatorMap([ 'I2SA' => ImportOfGoods::class, // Receipt of goods after advance payment 'I3SA' => ImportOfGoods::class, // 3ES Receipt of goods from EU 'I5SA' => ImportOfGoods::class, // 51 Receipt of goods without VAT 'I1SA' => ImportOfGoods::class, // 2LV Receipt of goods 'I9SA' => ImportOfGoods::class, // Medical goods receipt 'IPSA' => ImportOfGoods::class, // Receipt after inventory 'P1SA' => ImportOfGoods::class, // Receipt of samples LV 'IMSA' => ImportOfGoods::class, // 3rd country Receipt of goods Imports 'DBSA' => ImportOfGoods::class, // Business trip for goods delivery 'T1SA' => ImportOfGoods::class, // EU Transport service receipt from EU 'T2SA' => ImportOfGoods::class, // Transport service receipt ... 'R4AB' => SalesOfGoods::class, // Goods sale after advance payment 'ABAB' => SalesOfGoods::class, // Write-off for business needs 'E1AB' => SalesOfGoods::class, // 4ES Goods sale EU 0%;VAT43(4)16.16.Dir2006/11 'R1AB' => SalesOfGoods::class, // 1LV Goods sale 'E3AB' => SalesOfGoods::class, // EU Goods sale EU 21%; VAT law art.28.1. 'R9AB' => SalesOfGoods::class, // Medical goods sale 'ISAB' => SalesOfGoods::class, // Write-off after inventory ... 'M1AA' => InternalMovement::class, // Internal movement 'V2AS' => ReturnToSupplier::class, // Goods return to supplier 'V3AS' => ReturnToSupplier::class, // EU Goods return to EU; VAT law art.28.1. 'V4BA' => CustomerReturn::class, // Goods return from customer current rate 'V6BA' => CustomerReturn::class, // Goods return from EU 0% customer 'OFSB' => PurchaseOffer::class, // Advance payment; 21% 'EFSB' => PurchaseOffer::class, // OFFER PAYPER EU 0%;VAT law art.43. (4) 'N0SB' => CreditNote::class, // Credit invoice EU 0% 'K3SB' => CreditNote::class, // Credit invoice 3rd country 0% 'Y1SB' => ProformaInvoice::class, // Avansa rēķins no piegādātāja LV ar PVN 21% ... 'POAR' => ReservationOrRent::class, // Reservation 'PXPP' => InternalMovement::class, ]) ``` --- and unfortunately for me... I get it why it impossible... when doing `new CreditNote()` we don't know under which discriminatorValue to write N0SB or K3SB...
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#3467