5

我遇到了一个问题,它也可能放在programmers.stackexchange.com 上,但是由于它与Doctrine 和ZF2 非常相关,所以我选择把它放在这里。让我向您介绍我的场景:

  • 我有一个用户发布实体(BaseEntity)的应用程序。
  • BaseEntity有财产_$cagetory
  • 然而,取决于$category实体必须有额外的属性

Ab 简单示例:

class BaseEntity {
    protected $id;
    protected $title;
    protected $description;
}

class MovieEntity {
    protected $id;
    protected $title;
    protected $description;
    protected $airingDateStart; // new property
    protected $airingDateEnd;   // new property
}

现在我可以轻松地做一个两步公式,其中用户首先选择他的类别并根据将选择实体类 - 但我不能这样做。但这并不好,因为如果用户在BaseEntity-Category 中放置了电影,然后想将实体更改为 ,该MovieEntity怎么办?所以这个想法并不是一个安全的选择。

附加要求(使事情更复杂)

  • 类别和实体必须由 Doctrine 控制
  • 每个Category都通过单个提供给应用程序Module
  • 模块需要放置到应用程序中,不需要太多配置(最多一个 DB-Query 来填充CategoryTable

到目前为止我做了什么

起初我选择使用 Doctrines 功能Single Table Inheritance运行。这使我能够轻松地完成诸如MovieEntity extends BaseEntity向数据库添加新实体的魅力之类的事情。但主要问题仍然存在:如果用户更改类别怎么办,它会更改实体类,这几乎是不行的。

我的意思是,我可以按目前的方式做事,并在更改类别时手动修改,DiscriminatorColumn但这太脏了。

另一种替代方法是,在更改类别时,将创建一个新实体并销毁旧实体,但这也有点脏。

总而言之,我认为我走错了方向。可能有一个我不知道的开发模式,这让我所有的努力看起来都像是一种浪费,最终事情变得超级容易,但似乎我忽略了一些东西。

为了更深入地了解我的目标,您可以查看我在 GitHub 上的应用程序:

提前感谢我可能得到的所有反馈。我完全意识到这个问题可能介于 SO 与programmers.stackexchange 之间的存在之间,但我毕竟选择了它。

4

2 回答 2

3

如果我没看错你的情况,听起来你最好避免继承事物,而是将特定于类别的属性作为事物和类别之间关系的属性。

像这样的架构怎么样:

<?php

class Category {
    protected $id;
    protected $title;
    protected $things; //@ManyToOne(targetEntity="ThingCategory")
}

class Thing {
    protected $id;
    protected $title;
    protected $description;
    protected $category; //@ManyToOne(targetEntity="ThingCategory")
}    

/**
 * Use [Single|Class]-Table Inheritence to model subject-category attributes.
 * 
 * ThingCategory is just a base class.  Modules provide concrete subclasses
 * that encapsulate category-specific attributes.
 */
class ThingCategory {
    protected $id; //surrogate key, not strictly necessary
    protected $thing; //@ManyToOne(targetEntity="Thing")
    protected $category //@ManyToOne(targetEntity="Category")
}

class ThingMovieCategory extends ThingCategory{
    protected $airingStartDate;
    protected $airingEndDate;
}

class ThingCarCategory extends ThingCategory {
    protected $horespower;
    protected $numberOfDoors;
    protected $color;
}

因此,现在事物可以通过替换与其关联的 ThingCategory 实体在类别之间移动。事物的身份永远不会改变,只是与类别的关系。包含在该类别中所需的属性是 ThingCategory 关系实体的属性,而不是 Thing 本身的属性。

编辑:您可能遇到的问题是,在对实体进行子类化时,没有记录在案的方式来修改鉴别器映射。不幸的副作用是您的基本模块必须了解每个可能的模块。但这可能不是一个大问题。如果是这样,我相信可以通过让每个模块操作基本实体的 ClassMetaData 来避免这种情况,但我从来没有费心过实际进行这项工作。

于 2013-06-05T21:15:15.563 回答
1

您的问题是这句话“但主要问题仍然存在:如果用户更改类别怎么办,它会更改实体类,这几乎是不行的。”

一个类别不会真正改变,它会被删除,并被一个新的取代。因此,在您的代码中反映这一点,创建一个新实体,将其持久化,更新所有引用以指向新实体,然后删除旧实体。

于 2013-06-06T07:51:04.663 回答