Ответ 1
Это не хороший знак, когда тип экземпляра объекта должен меняться со временем. Я не говорю о downcasting/upcasting здесь, а о необходимости изменить реальный тип объекта.
Прежде всего, позвольте мне сказать вам, почему это плохая идея:
- Подкласс может определять больше атрибутов и выполнять некоторую дополнительную работу в нем конструктор. Должен ли мы снова запустить новый конструктор? Какие если он перезаписывает некоторые из наших старых атрибутов объекта?
- Что делать, если вы работаете над экземпляром этого Лица в некоторой части вашего кода, а затем он внезапно превращается в Employee (который может иметь какое-то переопределенное поведение, которого вы не ожидаете)?!
Это часть причины, по которой большинство языков не позволят вам изменять тип реального класса объекта во время выполнения (и, конечно, память, но я не хочу вдаваться в подробности). Некоторые позволяют вам это делать (иногда в скрученном виде, например, JVM), но это не очень хорошая практика!
Чаще всего необходимость в этом заключается в плохих объектно-ориентированных проектных решениях.
По этим причинам Doctrine не позволит вам изменить тип объекта объекта. Конечно, вы могли бы написать простой SQL (в конце этого сообщения, но, пожалуйста, прочитайте!), Чтобы сделать изменение в любом случае, но вот два "чистых" варианта, которые я бы предложил:
Я понимаю, что вы уже сказали, что первый вариант не был вариантом, но я потратил некоторое время на запись этого сообщения, поэтому мне кажется, что я должен сделать его максимально полным для будущей справки.
- Всякий раз, когда вам нужно "изменить тип" от
Person
доEmployee
, создайте новый экземпляр Employee и скопируйте данные, которые вы хотите скопировать из старого объекта Person, в объект Employee. Не забудьте удалить старый объект и сохранить новый. - Используйте композицию вместо наследования (см. статью wiki для получения более подробной информации и ссылок на другие статьи). РЕДАКТИРОВАТЬ: В черт, вот часть приятного разговора с Эрихом Гамма о "Композиции над наследством" "!
Смотрите связанные обсуждения здесь и здесь.
Теперь, вот простой метод SQL, о котором я говорил раньше, надеюсь, вам не понадобится его использовать!
Убедитесь, что ваш запрос очищен (так как запрос будет выполнен без какой-либо проверки).
$query = "UPDATE TABLE_NAME_HERE SET discr = 'employee' WHERE id = ".$entity->getId();
$entity_manager->getConnection()->exec( $query );
Вот документация и код метода exec, который находится в классе DBAL\Connection
(для вашей информации):
/**
* Execute an SQL statement and return the number of affected rows.
*
* @param string $statement
* @return integer The number of affected rows.
*/
public function exec($statement)
{
$this->connect();
return $this->_conn->exec($statement);
}