Как указать столбец внешнего ключа для наследования таблиц классов в Doctrine2? - PullRequest
3 голосов
/ 21 июля 2011

Как я могу указать столбцы, которые используются для отношения внешнего ключа с наследованием таблицы классов в Doctrine 2? Например, возьмите следующие два класса:

/**
 * @Entity
 * @InhertanceType("JOINED")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap("person" = "Person", "employee" = "Employee")
 */
class Person
{
    /** @Id */
    public $id;

    /** @Column(type="string") */
    public $ssn;
}

/** @Entity */
class Employee
{
    /** @Column(type="decimal") */
    public $salary;
}

При этом Doctrine ожидает структуру таблицы примерно так:

CREATE TABLE `person` (
    `id` INT(11) NOT NULL auto_increment,
    `ssn` VARCHAR(255) default NULL,
    PRIMARY_KEY(`id`)
)

CREATE TABLE `employee` (
    `person_id` INT(11) NOT NULL,
    `salary` DECIMAL(10,2) default NULL,
    PRIMARY_KEY(`person_id`)
)
ALTER TABLE `employee`
    ADD CONSTRAINT `person_fk` FOREIGN KEY (`person_id`)
        REFERENCES `person` (`id`) ON DELETE CASCADE

Существует внешний ключ employee.person_id, который указывает на person.id. Но как я могу сказать Doctrine, какие столбцы использовать? Я предполагаю, что ссылка person.id взята из аннотации @Id в классе Person, но что, если я хочу вместо этого создать FK для person.ssn (это возможно, поскольку SSN естественно уникальны).

А что, если у меня есть устаревшая база данных, где взамен employee.person_id называется employee.p_id?

1 Ответ

3 голосов
/ 12 октября 2011

Прежде всего, вам не хватает «extends Person» в определении класса Employee.

Из того, что я знаю, когда вы делаете этот тип наследования, доктрина использует первичный ключ в основном классе.для объединения всех других таблиц ожидается его поведение.

Когда вы выполняете запрос, доктрина объединяет все дочерние таблицы с родительскими, а затем выполняет гидратацию в соответствии с картой дискриминатора.Имея это в виду, не имеет значения, является ли ваш первичный ключ автоматически добавочным идентификатором или уникальным полем.Если вы определили ssn в родительском классе, он будет доступен для поиска во всех ваших подклассах.

Итак, пара советов здесь.Если хотите, вы можете удалить автоматический идентификатор и использовать ssn в качестве первичного ключа, а затем doctrine ожидает, что во всех ваших дочерних таблицах будет определено одно и то же поле.Для производительности может быть целесообразно иметь целое число вместо строки 255. Для выполнения объединений в любом случае.

Если вы хотите поддерживать автоматический идентификатор, вы можете добавить уникальный индекс в родительский класс, которыйТаким образом, если вы обращаетесь к классам по этому полю, вы не получите снижения производительности.

Если вы хотите, чтобы имя класса было чем-то, а имя таблицы - чем-то другим, используйте это

/** @Id @Column(name="p_id") */
public $id;

Но помните, что все таблицы, являющиеся частью наследования, должны использовать это имя.

Более того, я обычно использую доктрину для отображения существующей базы данных и ее расширения (переход к доктрине), и если яЯ добавляю новую функцию, а модель требует этого, я сам создаю отображение и таблицы, помня, как работает наследование Doctrines.Но если у вас есть существующие таблицы, которые, по вашему мнению, можно смоделировать с помощью Inheritance, следует ожидать некоторых проблем и, возможно, необходимости изменить существующие таблицы.

Надеюсь, это поможет.

...