Как изменить тип объекта в 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, чтобы отразить тот тип класса сущности, который только что был создан.
Надеюсь, это поможет. Это все в документации, хотя