Какую роль играет столбец `type` в наследовании таблицы классов Doctrine? - PullRequest
0 голосов
/ 08 апреля 2019

Использование Symfony 4 / Doctrine 2.6.У меня есть две сущности Post и Comment.Я хочу, чтобы оба были помечены тегами.Поэтому я создаю тег Tag.Я использую наследование таблиц классов Doctrine для создания отношения:

/**
 * @ORM\Entity(repositoryClass="App\Repository\TagRepository")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({"post" = "PostTag", "comment" = "CommentTag"})
 */
abstract class Tag
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $title;

    // Getters and setters...
}

/** @ORM\Entity */
class PostTag extends Tag
{
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Post", inversedBy="tags")
     */
    private $post;

    public function getPost(): ?Post
    {
        return $this->post;
    }
}

/** @ORM\Entity */
class CommentTag extends Tag
{
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Comment", inversedBy="comments")
     */
    private $comment;

    public function getComment(): ?Comment
    {
        return $this->comment;
    }
}

Это создает 3 таблицы: tag, post_tag и comment_tag.Структура таблицы post_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 ]

2 голосов
/ 08 апреля 2019

tl; dr: наследование - это неправильный инструмент. Тег является тегом является тегом. Наследование по своей природе обеспечивается использованием нескольких ассоциаций (многие-ко-многим).

Ваше наследство по сути говорит: есть два разных типа тегов, которые существенно различаются. Один тег, который можно применять к сообщениям, и один тег, который можно применять к комментариям, и это не те же теги, а разные теги.

Поскольку оба вида тегов хранятся в одной и той же таблице, должен существовать некоторый механизм, позволяющий отличать один от другого. Вот для чего предназначен столбец типа. (Так что, по сути, это ответ на ваш главный вопрос, афакт)

По сути, если вы хотите пометить комментарии и блог (посты) одинаково, это более распространенные варианты:

  1. Теги: (tag_id, tag_name, что угодно), Comment_tags: (tag_id, comment_id), Blog_tags: (tag_id, blog_id) ... (я полагаю, это то, что вы хотите / нужно)
  2. Теги: то же , Tagassignments: (tag_id, object_type, object_id) ... (неудобно в доктрине и в целом неблагоприятно¹)

Вы выбрали другой подход: теги: (tag_id, tag_name, object_type), Tagassignments: (tag_id, object_id) (<- тип объекта неявно задается tagid, но, поскольку вы используете отношения, Tagassignments разделяется в blog_tags и comment_tags) </p>

Однако, как правильно прокомментировал Магнус Эрикссон, это может иметь смысл. У меня есть сомнения. Я предполагаю, что либо вариант 1, либо вариант 2 гораздо более распространены и удобны. И вы должны отбросить наследование в теге и вместо этого добавить наследование в ассоциацию (если необходимо, вам нужно сделать его дополнительной сущностью, чтобы он работал), а лучше посоветовать выбрать вариант 1, потому что его проще реализовать с Учение и его аннотации. (хотя вам нужно было бы добавить один метод get {Object} s () для каждого типа объекта, который должен быть помечен тегами.)

¹ поскольку Магнус правильно комментирует ниже (и комментирует я): Вы теряете большинство преимуществ, которые предоставляют базы данных, в основном производительность, ясность и последовательность. Я бы вообще советовал против такого подхода.

0 голосов
/ 08 апреля 2019

Ради потомков, я использовал этот подход, чтобы реализовать ответ @ Jakumi:

  1. Очистить существующие таблицы.
  2. Создать объект Tagс консолью Symfony, со следующими полями:

    a) post (тип: отношение; многие-ко-многим)

    b) comment (тип: отношение; многие-to-many)

    c) title (тип: строка)

  3. Создание и запуск миграций.

Это автоматически создает таблицы tag_post и tag_comment.

...