Отображение доктрины для дискриминируемого класса, где столбец дискриминатора является частью ограничения уникальности

У меня плохо спроектированная база данных, где Entity-Attribute-Value шаблон был принят, и мне нужно настроить Учение 2.5 за.

Следующие таблицы иллюстрируют, как пользователь имеет свои свойства, хранящиеся в таблице свойств. Ниже приведены классы PHP для иллюстрации.

CREATE TABLE users (
user_id INT UNSIGNED AUTOINCREMENT PRIMARY KEY
);

INSERT INTO users (user_id) VALUES (123);

CREATE TABLE user_properties (
user_id INT UNSIGNED NOT NULL,
property_name VAR_CHAR(100) NOT NULL,
property_value VAR_CHAR(100),
PRIMARY KEY (user_id, property_name),
FOREIGN KEY (user_id) REFERENCES users(user_id)
);

INSERT INTO user_properties (user_id, property_name, property_value)
VALUES
(123, 'first_name', 'Joey Jo-Jo'),
(123, 'date_of_birth', '1978-01-01');

Я хотел бы сделать эти свойства конкретными объектами, которые доступны как отдельные свойства для объекта «Пользователь».

<?php
class User
{
/**
* @var \Doctrine\Common\Collections\ArrayCollection|AbstractUserProperies[]
*/
protected $properties;

public function getFirstName()
{
$firstNameProperty = $this->seekPropertyByType(UserFirstName::class);
return $firstNameProperty ? $firstNameProperty->getValue() : null;
}

public function getDateOfBirth()
{
$dobProperty = $this->seekPropertyByType(UserDateOfBirth::class);
return $dobProperty ? $dobProperty->getValue() : null;
}

protected function seekPropertyByType($className)
{
foreach ($this->properties as $property) {
if ($property instanceof $clasaName) {
return $property
}
}

return null;
}
}

abstract class AbstractUserProperty
{
/**
* @var User
*/
protect $user;

protected $value;

public function getValue()
{
return $this->value;
}
}

class UserFirstName extends AbstractUserProperty
{
public function setValue()
{
$this->value = (string)$value;
}
}

class UserDateOfBirth extends AbstractUserProperty
{
public function setValue(\DateTime $dob)
{
$this->value = $dob;
}
}

Далее я попытаюсь настроить эту настройку с помощью Doctrine.

<entity name="AbstractUserProperty" table="user_properties" inheritance-type="SINGLE_TABLE">
<discriminator-column name="property_name" type="string" />
<discriminator-map>
<discriminator-mapping value="first_name" class="UserFirstName"/>
<discriminator-mapping value="date_of_birth" class="UserDateOfBirth"/>
</discriminator-map>

<id name="user" type="integer" association-key="true" />
<id name="property_name" type="string" />

<many-to-one field="user" target-entity="User" inversed-by="properties">
<join-columns>
<join-column name="user_id" referenced-column-name="user_id" />
</join-columns>
</many-to-one>
</entity>

<entity name="UserFirstName">
<field name="value" column="property_value" type="string"/>
</entity>

<entity name="UserDateOfBirth">
<field name="value" column="property_value" type="datetime"/>
</entity>

<entity name="User">
<one-to-many field="properties" target-entity="AbstractUserProperty" mapped-by="user" fetch="EAGER">
<cascade>
<cascade-persist/>
</cascade>
</one-to-many>
</entity>

Проблема с этой конфигурацией в том, что мы получим ошибку от Doctrine, которая гласит:

Дублирующее определение столбца property_name в сущности AbstractUserProperty в отображении столбца поля или дискриминатора.

Это потому что property_name описывается как <discriminator-column> а также <id>, Но если я не сделаю этого, у меня может быть только одно свойство на Userгде мне нужно несколько.

Я также не могу переместить <id> к UserFirstName или же UserDateBirth потому что доктрина потом будет жаловаться на AbstractUserProperty не имея идентификатора — даже если это абстрактно.

Единственное, о чем я могу думать, это изменить user_properties таблица для включения суррогатного первичного ключа.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]