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

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

问题描述

有了这些课程,您将如何将Person的记录更改为Employee。

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
{
    // ...
}

我尝试更改了discriminator列的值,但我无法访问。我也尝试创建一个雇员实例并手动复制数据,但不适用于自动递增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?

推荐答案

当对象实例的类型需要随时间变化时,这不是一个好兆头。我不是在说这里的downcasting / upcasting,而是关于需要改变一个对象的真实类型。

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. 每当您需要从 Person Employee ,创建一个新的Employee实例,并将要复制的数据从旧的Person对象复制到Employee对象。不要忘记删除旧的实体并坚持新的实体。

  2. 使用组合而不是继承(请参阅 wiki文章,了解其他文章的详细信息和链接)。 编辑:对于其中的一部分,这里是与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"!

查看相关讨论这里 here

现在,这里是我之前提到的简单的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 );

这是在$ code> DBAL中的exec方法的文档和代码\Connection 类(为了您的信息):

Here is the documentation and code for the exec method which is in the DBAL\Connection 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天全站免登陆