2016-04-05 4 views
2

В моем приложении у меня есть несколько объектов, которые имеют общие свойства. Пример структуры:Наследование доктрины доктрины

  • Image
  • Видео
  • Событие
  • ForumPost

Я хочу, чтобы эти классы имеют некоторые общие функции, такие как:

  • Есть список комментариев, а также сохраняет количество комментариев
  • Голосование
  • Список абонентов и абонентов насчитывает
  • Посмотреть отсчитывает
  • и т.д ..

Я действительно не хотел бы дублировать эти функции для каждого из указанных лиц. Итак ... Я читал о картографировании наследования Doctrine, и я придумал идею о том, что «Class Table Inheritance» - самый элегантный способ решить эту проблему. План был следующим:

  1. Создание родительского сообщения сущность

    /** 
    * @ORM\Entity 
    * @ORM\InheritanceType("JOINED") 
    * @ORM\DiscriminatorColumn(name="type", type="string") 
    */ 
    class Post 
    { 
        protected $likeCount; 
    
        protected $subscriberCount; 
    
        protected $subscribers; 
    
        // ... 
    } 
    
  2. ли многие-к-одному отношения любит, комментарии, голоса и т.д., чтобы Опубликовать лицо:

    class PostLike 
    { 
        /** 
        * @ORM\ManyToOne(targetEntity="Post") 
        * @ORM\JoinColumn(name="post_id", referencedColumnName="id", nullable=false) 
        */ 
        protected $post; 
    } 
    
  3. Получить изображение, видео и т. Д. Сообщение:

    class Video extends Post 
    { 
        // Post properties become available here 
    } 
    

Все работало как шарм, пока я не посмотрел на фактические запросы, выполняемые Doctrine. Проблема в том, что всякий раз, когда я выбираю PostLike, доктрина будет также загружать объект Post, который, в свою очередь, также присоединяет все дочерние таблицы. Например, простая операция удаления PostLike запускает соединение на 4 таблицы и фактически присоединяется к еще большим таблицам по мере роста моей иерархии.

Если у меня есть 10 сущностей, расширяющих сообщение, это сделает соединение на 10 таблицах. Я не поклонник преждевременной оптимизации, но это просто не похоже на хороший план.

В документации Doctrine это поведение фактически упоминается в разделе «6.3.2. Эффективное воздействие».

Наконец, мой вопрос: Каковы мои другие варианты создания таблиц многократного использования с доктриной?

Я собирался сделать сопоставление «один-к-одному» (объект Post является свойством Video, а также Image и т. Д.), Но я прочитал в нескольких блогах, что One-to- Следует избегать доктрины также по соображениям производительности.

спасибо!

Редактировать и ansewer Рафаэлю Малых Что касается Подключенные Суперклассов:

Я знаю, что я могу использовать Подключенные суперкласса и Черта особенности, чтобы избежать дублирования кода. Однако эти функции позволяют мне повторно использовать код, но не позволяют мне повторно использовать таблицы sql. Вот пример:

Скажите, что я хочу, чтобы объекты изображений, видео и событий имели комментарии. Я могу создать один Соответствующий Суперкомплекс AbstractComment, а затем расширить его в ImageComment, VideoComment, EventComment. Затем я хочу добавить комментарии голосов. Поскольку я не могу повторно использовать ту же таблицу sql, мне нужно будет создать ImageCommentVote, VideoCommentVote, EventCommentVote и т. Д. Затем я хочу, чтобы пользователи могли сообщать о неправомерных комментариях. Идет еще раз: ImageCommentReport, VideoCommentReport, EventCommentReport. Вы поняли эту идею. Для каждой функции, которую я хочу добавить в комментарий, потребуется отдельная таблица для каждого объекта, такого как изображение, видео и т. Д. Множество таблиц.

Причина, почему я предпочитаю использовать централизованный подход вместо использования черт со многими таблицами:

  • Легче управление. Я могу легко найти/отредактировать/удалить комментарии всего приложения, отправив запрос в одну таблицу.
  • Тот же контроллер может обрабатывать действия для нескольких объектов, не нужно создавать один абстрактный и многие конкретные контроллеры.
  • Отображение пользовательских уведомлений о новых комментариях/предпочтениях и т. Д. Намного проще, когда действия централизованы.

Я также знаю о недостатках такой системы, но сейчас я могу жить с ними. Мой вопрос заключается в том, как заставить Доктрину делать то, что я хочу, фактически не присоединяясь ко всему, когда это не необходимо.

+0

Почти два года спустя мне очень любопытно, с каким решением вы столкнулись? – BigJ

ответ

1

По-моему, вы поступаете неправильно. У ваших сущностей нет ничего общего, кроме некоторых функций, поэтому нет причин использовать single table или class table наследование.

Вы должны использовать Черты характера: http://php.net/manual/en/language.oop5.traits.php

Он работает с доктриной. Вы определяете одну или несколько признаков с некоторыми свойствами/методами с аннотациями, а затем импортируете эти признаки в свои объекты.

Вы также можете использовать Mapped Superclass: http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#mapped-superclasses, который довольно близок к вашему примеру, но с другой аннотацией объекта.

+0

Черты и сопоставленные суперклассы заставят меня использовать таблицу различных комментариев (например) для каждого объекта. Поэтому мне придется использовать VideoComment, ImageComment, EventComment и т. Д. Затем, если я хочу добавить голосование по комментариям, мне нужно будет использовать VideoCommentVote, ImageCommentVote, ... Таким образом, иерархия будет расти с каждой добавленной мной особенностью комментария. То, что я хочу сделать, это создать единый объект комментария, который может быть связан либо с видео, либо с изображением, либо с любым другим классом. То же самое касается симпатий, подписчиков и т. Д. – Karolis

0

После некоторого размышления ваше решение действительно зависит от размера вашей базы данных. Если он большой, удар производительности класса Tabel может быть неприемлемым. Но если ваши таблицы небольшие, то поражение производительности незначительно, и вы можете использовать все преимущества класса Table Inheritance, о которых вы говорили сами в своем посте.

Смежные вопросы