我正面临一个问题,也可能放在programmers.stackexchange.com上,但由于它与Doctrine和ZF2非常相关,所以我选择将它放在这里 . 让我向您介绍我的方案:
-
我有一个用户发布实体的应用程序(
BaseEntity
) . -
BaseEntity
有 property$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
}
现在我可以很容易地做一个两步的公式,用户首先选择他的类别,并根据它选择EntityClass - 但我可以't have that. But that'不好,因为如果用户在 BaseEntity
-Category中放置一个电影然后然后后来想把实体改成 MovieEntity
?所以这个想法并不是一个安全的选择 .
Additional Requirements (使事情更复杂)
-
类别和实体必须由Doctrine控制
-
每个
Category
都通过单个Module
提供给应用程序 -
模块需要放入应用程序而无需太多配置(最多一个DB-Query填充
CategoryTable
)
What i did so far
起初我选择使用Doctrines功能运行 Single Table Inheritance . 这使我能够轻松地完成诸如_430753之类的事情,并且事情就像一个用于向数据库添加新实体的魅力 . 但主要问题仍然存在:如果用户更改了类别,它将改变EntityClass,这几乎是一个禁忌 .
我的意思是,我可能会以当前的方式做事情,并且在类别的更改上手动修改 DiscriminatorColumn
,但这太肮脏了 .
另一种替代方法是,如果更改类别,将创建一个新实体,旧实体将被销毁,但这也有点脏 .
总而言之,我认为我走向了错误的方向 . 可能有一种我不知道的开发模式,这使得我的所有努力工作看起来都是浪费,最终事情变得非常简单,但看起来我忽略了一些东西 .
为了更好地了解我的目标,你可以看看我在GitHub上的应用程序:
-
DuitMarketplace - 这是一个带有基类,所有控制器等的主要应用程序...... ItemController#editAction()可能会提供更多关于我打算如何自动制作一些东西的线索 .
-
DuitMarketplaceItemVehicle - 一个被放入mainapp的类别
在此先感谢您收到的所有反馈 . 我完全意识到这个问题可能是SO与programmers.stackexchange存在之间的边界,但我毕竟选择了它 .
2 回答
如果我正确地阅读你的情况,听起来你可以通过避免对Thing的继承而更好地服务,而是将类别特定属性作为事物和类别之间关系的属性 .
这样的架构怎么样:
所以,现在事物可以通过替换与之关联的ThingCategory实体在类别之间移动 . 事物的身份永远不会改变,只是它与类别的关系 . 包含在该类别中所需的属性是ThingCategory关系实体的属性,而不是Thing本身的属性 .
编辑:您可能遇到的问题是,在子类化实体时没有记录的修改鉴别器映射的方法 . 不幸的副作用是你的基础模块必须知道每个可能的模块 . 但这可能不是一个大问题 . 如果是,我相信可以通过让每个模块操纵基本实体的ClassMetaData来避免这种情况,但我从来没有打扰过实际的工作 .
你的问题就是这句话“但主要的问题仍然存在:如果用户更改了类别,它会改变EntityClass,这几乎就是禁忌 . ”
一个类别不会真正改变,它将被删除,并替换为一个新类别 . 因此,在您的代码中反映这一点,创建一个新实体,持久化,更新所有引用以指向新实体,然后删除旧实体 .