It is after having searched arround doctrine doc that I come to ask this question which is software design related.
A class B inherits from a class A.
The class B cannot declare a uniqueness constraint on the fields of the class A and those of the class B because, as they both represent two different table, a table B can’t define constraint for table A fields.
Indeed, when trying to update the database, we get this nice error message:
C:wamp64www...>php bin/console doctrine:schema:update --force
In SchemaException.php line 86:
There is no column with name 'parameter' on table 'setting_company'.
Here is a code snippet for some context:
The ‘parent’ Setting entity from which the SettingCompany entity inherits:
/**
* @ORMEntity()
* @ORMDiscriminatorMap(
* value={
* Setting::COMPANY=SettingCompany::class,
* Setting::COMPANY_GROUP=SettingCompanyGroup::class, // <- class not represented in this snippet
* Setting::GROUP=SettingGroup::class, // <- class not represented in this extract
* Setting::USER=SettingUser::class, // <- class not represented in this snippet
* }
* )
* @ORMDiscriminatorColumn(name="d_type", type="string", length=10)
* @ORMInheritanceType(value="JOINED")
*/
abstract class Setting implements ParameterHolderInterface
{
const COMPANY = 'company';
const COMPANY_GROUP = 'compgrp';
const GROUP = 'group';
const USER = 'user';
/**
* @ORMId()
* @ORMColumn(type="integer")
* @ORMGeneratedValue(strategy="IDENTITY")
*/
protected ?int $id = null;
/**
* @ORMManyToOne(targetEntity="AppDomainParameterEntityParam")
* @ORMJoinColumn(name="parameter", nullable=false, referencedColumnName="code", onDelete="CASCADE")
*/
protected Param $param;
// ... Other fields not relevant to the problem
}
SettingCompany which inherits from Setting :
/**
* @ORMTable(uniqueConstraints={@ORMUniqueConstraint(name="unq_param_company", columns={"parameter", "company"})}) <-- The problem is here
* @ORMEntity(repositoryClass="AppDomainSettingRepositorySettingCompanyRepository")
*/
class SettingCompany extends Setting
{
/**
* @ORMManyToOne(targetEntity="AppEntityCompany", cascade={"remove"})
* @ORMJoinColumn(name="company", referencedColumnName="code", onDelete="CASCADE")
*/
private Company $company;
//... Other fields not relevant to solving the problem
}
Of course, this is because I’m trying to define a unique constraint on two fields which are not in the same table.
If I change the inheritanceType for SINGLE_TABLE it’ll work, but it’ll come with serious performance issue when fetching data so I won’t do that.
What I really want to have is this ‘super’ entity Setting so I can manage every sub-Setting entity in the same way through the same interface.
So, I’ve already tried moving the $param field, directly into the child classes. This works, but it is not at all what I want to do.
And I can’t use composed primary key, because doctrine is really bad at handling those one (Can’t make ManyToMany from a ‘composed key entity’). This is really painfull not to be able to use it.
So this is a design issue…