首页 文章

如何处理不同实体类别的不同实体属性

提问于
浏览
5

我正面临一个问题,也可能放在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上的应用程序:

在此先感谢您收到的所有反馈 . 我完全意识到这个问题可能是SO与programmers.stackexchange存在之间的边界,但我毕竟选择了它 .

2 回答

  • 1

    如果我正确地阅读你的情况,听起来你可以通过避免对Thing的继承而更好地服务,而是将类别特定属性作为事物和类别之间关系的属性 .

    这样的架构怎么样:

    <?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来避免这种情况,但我从来没有打扰过实际的工作 .

  • 3

    你的问题就是这句话“但主要的问题仍然存在:如果用户更改了类别,它会改变EntityClass,这几乎就是禁忌 . ”

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

相关问题