Как изменить тип объекта в Doctrine2 CTI Inheritance

Как (если возможно вообще) вы изменяете тип сущности с помощью Doctrine2, используя его наследование класса Class?

Скажем, у меня есть тип родительского класса Person и два унаследованных типа Employe и Client. Моя система позволяет создать Person и указать его тип, который довольно легко реализовать, но я также хотел бы иметь возможность изменять человека от Employee к клиенту, сохраняя при этом информацию уровня Person (это идентификатор и другие связанные записи).

Есть ли простой способ сделать это с помощью Doctrine2?

Ответ 1

Я тоже искал это поведение вчера.

В конце концов, поговорив с людьми в #doctrine на freenode, мне сказали, что это невозможно.

Если вы хотите это сделать, вам нужно пройти через это:

Обновление пользователя

  • Возьмите Entity Person.
  • Обновите столбец дискриминатора, чтобы он больше не был "человеком" и изменил его на "employee"
  • Создайте соответствующую строку в вашей таблице Employee для этого наследования.

Удаление наследования

Аналогично, если вы хотите удалить наследование, вам нужно...

  • Возьмите Entity Person.
  • Обновите столбец дискриминатора, чтобы он больше не являлся "сотрудником" и менял его на "человека".
  • Удалите соответствующую строку в таблице Employee. (Да, вы должны удалить его, просто изменить дискриминатор coumn недостаточно).

Возможно, это может быть на 7 месяцев, но это, по крайней мере, правильный ответ на все, что нужно, чтобы поддержать такую ​​функцию.

Ответ 2

У PHP нет поддержки для создания объектов, поэтому Doctrine не поддерживает его. Чтобы обойти проблему, я пишу этот статический метод в родительские классы:

public static function castToMe($obj) {

    $class = get_called_class();
    $newObj = New $class();

    foreach (get_class_vars(get_class($newObj)) as $property => $value) {
        if (method_exists($obj, 'get' . ucfirst($property)) && method_exists($newObj, 'set' . ucfirst($property))) {
            $newObj->{'set' . ucfirst($property)}($obj->{'get' . ucfirst($property)}());
        }
    }

    return $newObj;
}

Вы можете создать этот метод в классе Person и использовать его для переноса из Employe to Client и наоборот:

$employe = New Employe();
$client = Client::castToMe($employe);

Теперь, если вы хотите, вы можете удалить объект $employe.

Ответ 3

В Doctrine2, когда у вас есть родительский класс сущности, Person устанавливается как:

/**
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"person" = "Person", "employee" = "Employee", , "client" = "Client"})
 */
class Person
{
    // ...
}

и подклассы, такие как Client установлены как:

/** @Entity */
class Client extends Person
{
    // ...
}

когда вы создаете экземпляр Person как:

$person = new Person();

Doctrine2 проверяет ваш оператор @DiscriminatorMap (см. Выше) на предмет соответствующего сопоставления с Person и, когда он найден, создает строковое значение в столбце таблицы, установленном в @DiscriminatorColumn выше.

Поэтому, когда вы решите использовать экземпляр Client как:

$client = new Client();

Следуя этим принципам, Doctrine2 будет создавать для вас экземпляр, если вы объявили параметры в @DiscriminatorMap. Также будет сделана запись в таблице Person в столбце discr, чтобы отразить тот тип класса сущности, который только что был создан.

Надеюсь, это поможет. Это все в документации, хотя