教义类表继承中的"类型"列扮演什么角色?



Using Symfony 4/Doctrine 2.6.我有两个实体发布和评论。我希望两者都是可标记的。所以我创建了一个实体标签。我使用 Doctrine 的类表继承来创建关系:

/**
* @ORMEntity(repositoryClass="AppRepositoryTagRepository")
* @ORMInheritanceType("JOINED")
* @ORMDiscriminatorColumn(name="type", type="string")
* @ORMDiscriminatorMap({"post" = "PostTag", "comment" = "CommentTag"})
*/
abstract class Tag
{
/**
* @ORMId()
* @ORMGeneratedValue()
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMColumn(type="string", length=255)
*/
private $title;
// Getters and setters...
}
/** @ORMEntity */
class PostTag extends Tag
{
/**
* @ORMManyToOne(targetEntity="AppEntityPost", inversedBy="tags")
*/
private $post;
public function getPost(): ?Post
{
return $this->post;
}
}
/** @ORMEntity */
class CommentTag extends Tag
{
/**
* @ORMManyToOne(targetEntity="AppEntityComment", inversedBy="comments")
*/
private $comment;
public function getComment(): ?Comment
{
return $this->comment;
}
}

这将创建 3 个表:tagpost_tagcomment_tagpost_tag表结构如下所示:

id | post_id

tag表结构如下所示:

id | title | type

例如,帖子和标签是如何关联的?如果我想将帖子13与标签test相关联,结果会是这样的:

post_tag表:

id | post_id
------------
1  | 13

tag表:

id | title | type
-----------------
1  | test  | post

如果是这样,那么如果我想将相同的标签(test)与注释相关联怎么办。那么tag表会是这样的吗?

id | title | type
--------------------
1  | test  | post
2  | test  | comment

这似乎有点多余。然后,同一实体(test标记)由tag表中的 2 行表示。我弄错了吗?

tl;大卫:继承是错误的工具。标签就是标签就是标签。继承本质上是通过使用多个关联(多对多)提供的。

你的继承本质上是说:有两种不同类型的标签,本质上是不同的。一个标签可以应用于帖子,一个标签可以应用于评论,它们不是相同的标签,而是不同的标签。

由于这两种标签都存储在同一个表中,因此必须有一些机制来区分其中一种。这就是类型列的用途。(所以,这基本上是你主要问题的答案,afaict)

因此,从本质上讲,如果您想标记评论和博客(帖子),这些是更常见的选项:

标签: (tag_id, tag_name, 随便), Comment_tags: (tag_id,
  1. comment_id), Blog_tags: (tag_id, blog_id) ...(我假设,这就是你想要/需要的)
  2. 标签:相同, 标签分配: (tag_id, object_type, object_id) ...(在教义上不方便,总体上不利¹)

您选择了不同的方法:标签:(tag_id、tag_name、object_type)、标签分配:(tag_id、object_id)(<-对象类型由tagid隐式给出,但由于您使用的是关系,标签分配分为blog_tags和comment_tags)

然而,正如马格努斯·埃里克森(Magnus Eriksson)正确评论的那样,这可能是有道理的。我有我的怀疑。我认为,选项 1 或选项 2 更常见和方便。您应该删除标签上的继承,而是在关联上添加继承(如果需要,您需要使其成为额外的实体以使其工作),而是建议选择选项 1,因为它更容易实现与原则和它的注释。(尽管您需要为每个应该可标记的不同对象类型添加一个 get{Object}s()。

¹正如Magnus在下面正确评论的那样(并由我共同评论):你失去了数据库提供的大部分优势,主要是性能,清晰度和一致性。我一般建议不要这样做。

为了后代,这是我实现@Jakumi答案的方法:

  1. 废弃现有表。
  2. 使用symfony控制台创建一个Tag实体,具有以下字段:

    a)post(类型:关系;多对多)

    b)comment(类型:关系;多对多)

    c)title(类型:字符串)

  3. 进行和运行迁移。

这会自动创建表tag_posttag_comment

相关内容

  • 没有找到相关文章

最新更新