Short question: can I avoid generating foreign keys for inherited classes to parent classes? Can a discriminator column for inherintance mapping be set in a relation owner instead of a parent class?
Explanation:
I am designing a model for invoices, where invoice subject can be 1 of 3 types:
- Contract
- Client
- Provider
After reading Doctrine inheritance mapping I think Class table inheritance is the one that best fits my needs.
Mapped superclass could better fit my needs if I could draw a relation from Invoice
to InvoiceSubject
, but I think I can't:
A mapped superclass cannot be an entity, it is not query-able and persistent relationships defined by a mapped superclass must be unidirectional (with an owning side only). This means that One-To-Many associations are not possible on a mapped superclass at all. Furthermore Many-To-Many associations are only possible if the mapped superclass is only used in exactly one entity at the moment.
Also, using an Interface could be a solution, but an interface in a relation can only be mapped to one entity.
So, this is my model:
/**
* @ORM\Entity
*/
class Invoice
{
/**
* @ORM\ManyToOne(targetEntity="InvoiceSubject")
* @var InvoiceSubject
*/
protected $subject;
}
/**
* @ORM\Entity
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="invoicesubject_type", type="string")
* @ORM\DiscriminatorMap({"invoice-subject" = "InvoiceSubject", "contract" = "Contract", "provider" = "Provider", "client" = "Client"})
*/
class InvoiceSubject
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $id;
}
/**
* @ORM\Entity
*/
class Contract extends InvoiceSubject{}
/**
* @ORM\Entity
*/
class Provider extends InvoiceSubject implements ProviderInterface{}
/**
* @ORM\Entity
*/
class Client extends InvoiceSubject{}
But, when I try to generate the model (bin/console doctrine:schema:update --dump-sql
) I see its trying to create foreign keys from child classes to parent (tables already exist and have data):
ALTER TABLE contract ADD CONSTRAINT FK_E9CCE71ABF396750 FOREIGN KEY (id) REFERENCES invoice_subject (id) ON DELETE CASCADE;
ALTER TABLE provider ADD CONSTRAINT FK_B2F1AF1BBF396750 FOREIGN KEY (id) REFERENCES invoice_subject (id) ON DELETE CASCADE;
ALTER TABLE client ADD CONSTRAINT FK_B2F1AF1BBF396750 FOREIGN KEY (id) REFERENCES invoice_subject (id) ON DELETE CASCADE;
This means that there will be collisions between id's coming from different tables or I will need to use different values in every table, none of the solutions are good. So, the question is:
- Is there a way to avoid this foreign key and set the discriminator in the relation owner class
Invoice
? In my case,InvoiceSubject
doen't actually need to exist as a table, I'm forced to create it as Class table inheritance forces me to do so. - Or, is this modelling completely wrong and I should use another aproach?