Doctrine ORM 和具有抽象 类 策略的工厂
Doctrine ORM and factories with abstract classes strategy
所以我偶然发现了这个障碍,我必须创建一个抽象 class 和一个工厂来创建更具体的 classes 的对象,这些对象扩展了抽象 class 和实现更具体的对象方法。
简单地说,我得到了一个 SocialMediaAbstract class。扩展 classes 是 Facebook、Instagram,它们实现了 SocialMediaInterface。 Facebook、Instagram 等都保存在数据库中,有一个 id、一个名称和几个在扩展 class 中使用的更多属性,因此是一个抽象 class.
因为我希望能够从 SocialMedia Objects 中查询一些东西,而且每个社交媒体平台都有自己的 API,所以我制作了界面并创建了不同的 classes 以便它们都可以这些方法有自己的实现。
现在,问题当然出在我的抽象 class 和 Doctrine 上。 Doctrine 在他们的 website regarding inheritance:
上这样说
A mapped superclass cannot be an entity, it is not query-able [...]
现在,如果我有一个 SocialMediaFactory 并输入一个 ID,我想取回各自的对象,例如 class Facebook 或 Instagram。我不想在收集它们时确切地知道它是哪个社交媒体。现在这是学说的问题,至少我是这么认为的。
我是不是忽略了什么,工厂模式还能用吗?或者我真的应该删除抽象 class,并创建一个工厂来搜索实现 class 的 SocialMediaInterface 的每个 table,当一个应用程序变大了。
如有任何见解或指点,我们将不胜感激,因为我确信这个问题肯定更常出现。我尝试在 Whosebug 本身上进行谷歌搜索和搜索,但找不到任何相关问题或答案。
非常感谢您。
编辑:
我遇到了这个有趣的可能性:Class Table Inheritance。这意味着添加:
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"facebook" = "Facebook", "instagram" = "Instagram"})
到我的代码。我寄予厚望,但遗憾的是验证器给了我这个错误:
[Doctrine\ORM\Mapping\MappingException]
It is not supported to define inheritance information on a mapped superclas
s 'Portal\SocialMedia\Entity\SocialMediaAbstract'.
不支持羞耻映射器超级classes。
编辑 2/结论:
我决定使用 Class Table 继承(就像下面建议的答案一样)。从 class 中删除摘要使得仍然可以使用我的工厂成为可能。
我现在使用具体的 class 作为抽象的 class,但感觉不对。我在 docblock 中记录了不应从此 class.
实例化任何对象
一点旁注:Doctrine 的实体管理器或多或少已经提供了工厂:
$socialMedia = $entityManager->find('Portal\SocialMedia\Entity\SocialMedia', 2);
这 returns 一个 Instagram 对象。我仍然建议您在其上方构建自己的工厂以便稍后维护,因为 SocialMedia 实体稍后可能会更改。
自从我从事教义工作以来已经过去了一段时间,但如果我没记错的话,doctrine's mapped super classes are an implementation of the concrete table inheritance pattern 作者 Martin Fowler。
在那里提到的示例中,Player
是映射的超 class,其属性分布到所有继承实体/模型。这里的要点是玩家不能被实例化,因此没有自己的 id。相反,每个继承模型都有自己的 id,它们彼此独立。
我认为您正在寻找的模式是 single table inheritance or class table inheritance (have a look at doctrine's inheritance types).
Single table inheritance 在学说的继承类型 "SINGLE_TABLE" 中实现,其中所有实体都有一个 table。它们共享完全相同的属性和相同的 ID 池,这意味着您可以 "throw in" 一个 ID,获取对象并检查类型(Facebook、Instagram 等)。
缺点是,如果您在任何一个实体中得到一个可能 NULL
的属性,如果其他实体没有或没有此属性,您可能 运行 会遇到问题不需要它。这意味着您必须将给定属性设置为其他实体中的虚拟值才能将它们保存到数据库中 table.
Class table inheritance 通过将每个实体保存在自己的 table 中来解决这个问题,同时仍然能够共享 id 池,因为学说会注意将公共属性保存在基础 class table,而实体特有的所有属性都保存在实体的table中。然后 table 由 id 连接,因此在学说中继承类型 "JOINED"。
结论:
如果class非常相似,仅在功能定义或实现上不同,但具有相同的属性,则使用single table inheritance。
如果 classes 具有不同的属性,存储在单个 table 中会出现问题,请使用 class table inheritance。
使用concrete table inheritance if the classes are not really related to each other, but only share a small amount of common attributes. But this could also be implemented through PHP's traits,在我看来比doctrine的mapped superclass更容易、更灵活使用。在 PHP trait 中,你也可以使用 doctrine 的注解,因为 PHP 解释器会正确地将注解分配给你在其中使用 trait 的 classes。
您应该仍然可以使用单一 table 或 class table 继承模式的 SocialMediaFactory。
所以我偶然发现了这个障碍,我必须创建一个抽象 class 和一个工厂来创建更具体的 classes 的对象,这些对象扩展了抽象 class 和实现更具体的对象方法。
简单地说,我得到了一个 SocialMediaAbstract class。扩展 classes 是 Facebook、Instagram,它们实现了 SocialMediaInterface。 Facebook、Instagram 等都保存在数据库中,有一个 id、一个名称和几个在扩展 class 中使用的更多属性,因此是一个抽象 class.
因为我希望能够从 SocialMedia Objects 中查询一些东西,而且每个社交媒体平台都有自己的 API,所以我制作了界面并创建了不同的 classes 以便它们都可以这些方法有自己的实现。
现在,问题当然出在我的抽象 class 和 Doctrine 上。 Doctrine 在他们的 website regarding inheritance:
上这样说A mapped superclass cannot be an entity, it is not query-able [...]
现在,如果我有一个 SocialMediaFactory 并输入一个 ID,我想取回各自的对象,例如 class Facebook 或 Instagram。我不想在收集它们时确切地知道它是哪个社交媒体。现在这是学说的问题,至少我是这么认为的。
我是不是忽略了什么,工厂模式还能用吗?或者我真的应该删除抽象 class,并创建一个工厂来搜索实现 class 的 SocialMediaInterface 的每个 table,当一个应用程序变大了。
如有任何见解或指点,我们将不胜感激,因为我确信这个问题肯定更常出现。我尝试在 Whosebug 本身上进行谷歌搜索和搜索,但找不到任何相关问题或答案。
非常感谢您。
编辑: 我遇到了这个有趣的可能性:Class Table Inheritance。这意味着添加:
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"facebook" = "Facebook", "instagram" = "Instagram"})
到我的代码。我寄予厚望,但遗憾的是验证器给了我这个错误:
[Doctrine\ORM\Mapping\MappingException] It is not supported to define inheritance information on a mapped superclas s 'Portal\SocialMedia\Entity\SocialMediaAbstract'.
不支持羞耻映射器超级classes。
编辑 2/结论: 我决定使用 Class Table 继承(就像下面建议的答案一样)。从 class 中删除摘要使得仍然可以使用我的工厂成为可能。
我现在使用具体的 class 作为抽象的 class,但感觉不对。我在 docblock 中记录了不应从此 class.
实例化任何对象一点旁注:Doctrine 的实体管理器或多或少已经提供了工厂:
$socialMedia = $entityManager->find('Portal\SocialMedia\Entity\SocialMedia', 2);
这 returns 一个 Instagram 对象。我仍然建议您在其上方构建自己的工厂以便稍后维护,因为 SocialMedia 实体稍后可能会更改。
自从我从事教义工作以来已经过去了一段时间,但如果我没记错的话,doctrine's mapped super classes are an implementation of the concrete table inheritance pattern 作者 Martin Fowler。
在那里提到的示例中,Player
是映射的超 class,其属性分布到所有继承实体/模型。这里的要点是玩家不能被实例化,因此没有自己的 id。相反,每个继承模型都有自己的 id,它们彼此独立。
我认为您正在寻找的模式是 single table inheritance or class table inheritance (have a look at doctrine's inheritance types).
Single table inheritance 在学说的继承类型 "SINGLE_TABLE" 中实现,其中所有实体都有一个 table。它们共享完全相同的属性和相同的 ID 池,这意味着您可以 "throw in" 一个 ID,获取对象并检查类型(Facebook、Instagram 等)。
缺点是,如果您在任何一个实体中得到一个可能 NULL
的属性,如果其他实体没有或没有此属性,您可能 运行 会遇到问题不需要它。这意味着您必须将给定属性设置为其他实体中的虚拟值才能将它们保存到数据库中 table.
Class table inheritance 通过将每个实体保存在自己的 table 中来解决这个问题,同时仍然能够共享 id 池,因为学说会注意将公共属性保存在基础 class table,而实体特有的所有属性都保存在实体的table中。然后 table 由 id 连接,因此在学说中继承类型 "JOINED"。
结论:
如果class非常相似,仅在功能定义或实现上不同,但具有相同的属性,则使用single table inheritance。
如果 classes 具有不同的属性,存储在单个 table 中会出现问题,请使用 class table inheritance。
使用concrete table inheritance if the classes are not really related to each other, but only share a small amount of common attributes. But this could also be implemented through PHP's traits,在我看来比doctrine的mapped superclass更容易、更灵活使用。在 PHP trait 中,你也可以使用 doctrine 的注解,因为 PHP 解释器会正确地将注解分配给你在其中使用 trait 的 classes。
您应该仍然可以使用单一 table 或 class table 继承模式的 SocialMediaFactory。