Doctrine:更新 SINGLE_TABLE 继承的鉴别器 [英] Doctrine: Update discriminator for SINGLE_TABLE Inheritance

查看:24
本文介绍了Doctrine:更新 SINGLE_TABLE 继承的鉴别器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过这些类,您将如何将人"的记录更改为员工".

With these classes, how would you change a record for a "Person" to an "Employee".

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

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

我尝试更改鉴别器列的值,但无法访问该值.我还尝试创建一个员工"实例并手动复制数据,但这不适用于自动递增的 ID.它只是作为新记录添加,而不是更新现有记录.

I tried changing the value of the discriminator column but I can't access that. I also tried creating an 'Employee' instance and manually copy the data over but that doesn't work with auto-incrementing id's. It just gets added as a new record instead of updating the existing one.

我是否需要编写自定义 sql 查询,还是我在做其他根本错误的事情?

Do I need to write a custom sql query or am I doing something else that is fundamentally wrong?

推荐答案

当对象实例的类型需要随时间改变时,这不是一个好兆头.我在这里不是在谈论向下转型/向上转型,而是谈论需要改变对象的真实类型.

It is not a good sign when the type of an instance of an object needs to change over time. I'm not talking about downcasting/upcasting here, but about the need to change the real type of an object.

首先,让我告诉你为什么这是一个坏主意:

First of all, let me tell you why it is a bad idea:

  1. 一个子类可能会定义更多的属性并做一些额外的工作在它的构造函数中.我们应该再次运行新的构造函数吗?什么如果它覆盖了我们旧对象的一些属性?
  2. 如果您在代码的某些部分处理该 Person 的实例,然后它突然转换为 Employee(可能有一些您意想不到的重新定义的行为)怎么办?!

这就是为什么大多数语言不允许您在执行期间更改对象的真实类类型(当然还有内存,但我不想详细介绍)的部分原因.有些让你这样做(有时以扭曲的方式,例如 JVM),但这真的不是一个好习惯!

That is part of the reason why most languages will not allow you to change the real class type of an object during execution (and memory, of course, but I don't want to get into details). Some let you do that (sometimes in twisted ways, e.g. the JVM), but it's really not good practice!

通常情况下,这样做的需要在于糟糕的面向对象设计决策.

More often than not, the need to do so lies in bad object-oriented design decisions.

出于这些原因,Doctrine 不允许您更改实体对象的类型.当然,您可以编写简单的 SQL(在本文末尾 - 但请通读!)无论如何都要进行更改,但我建议这里有两个干净"的选项:

我意识到你已经说过第一个选项不是一个选项,但我花了一段时间写下这篇文章,所以我觉得我应该让它尽可能完整以备将来参考.

  1. 每当您需要更改类型"从 PersonEmployee 时,请创建 Employee 的新实例并复制您要从旧数据复制过来的数据Person 对象转为 Employee 对象.不要忘记删除旧实体并保留新实体.
  2. 使用组合代替继承(有关详细信息和其他文章的链接,请参阅此维基文章).该死的,这里是一个不错的部分与 Erich Gamma 的对话关于组合优于继承"!
  1. Whenever you need to "change the type" from Person to Employee, create a new instance of the Employee and copy the data you want to copy over from the old Person object to the Employee object. Don't forget to remove the old entity and to persist the new one.
  2. Use composition instead of inheritance (see this wiki article for details and links to other articles). For the hell of it, here's a part of a nice conversation with Erich Gamma about "Composition over Inheritance"!

查看相关讨论此处此处.

现在,这是我之前谈到的纯 SQL 方法 - 我希望您不需要使用它!

确保您的查询经过清理(因为查询将在没有任何验证的情况下执行).

Make sure your query is sanitized (as the query will be executed without any verification).

$query = "UPDATE TABLE_NAME_HERE SET discr = 'employee' WHERE id = ".$entity->getId();
$entity_manager->getConnection()->exec( $query );

以下是 DBALConnection 类中 exec 方法的文档和代码(供您参考):

Here is the documentation and code for the exec method which is in the DBALConnection class (for your information):

/**
 * 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);
}

这篇关于Doctrine:更新 SINGLE_TABLE 继承的鉴别器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆