Учение ОРМ и фабрики с абстрактной стратегией классов

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

Проще говоря, я получил класс SocialMediaAbstract. Расширяющие классы — это Facebook, Instagram, и они реализуют интерфейс SocialMediaInterface. Facebook, Instagram и т. Д. Все сохраняются в БД с идентификатором, именем и еще несколькими свойствами, которые используются среди расширяющихся классов, следовательно, абстрактного класса.

Поскольку я хочу иметь возможность запрашивать несколько вещей из объектов SocialMedia, и у каждой платформы социальных сетей есть свои собственные API-интерфейсы для этого, я создал интерфейс и создал различные классы, чтобы у всех них была своя реализация этих методов.

Теперь проблема, конечно, с моим абстрактным классом и Доктриной. Учение говорит это на их сайт о наследовании:

Сопоставленный суперкласс не может быть сущностью, он не способен выполнять запросы […]

Теперь, если у меня есть SocialMediaFactory и я добавил ID, я бы хотел получить соответствующий объект, например, класса Facebook или Instagram. Я не хочу точно знать, что это за SocialMedia, когда я их собираю. Это проблема доктрины, по крайней мере, я так думаю.

Я что-то упускаю, возможна ли заводская модель? Или я действительно должен просто удалить абстрактный класс и создать фабрику, которая ищет в каждой таблице реализующий класс SocialMediaInterface, который кажется крайне неэффективным и неуправляемым, когда приложение становится больше.

Любое понимание или указатели будут оценены, так как я уверен, что эта проблема, должно быть, возникала чаще. Я попытался поискать в Google и искать в самом Stackoverflow, но не смог найти ни одного уместного вопроса или ответа.

Заранее большое спасибо.

РЕДАКТИРОВАТЬ:
Я наткнулся на эту интересную возможность: Наследование таблицы классов. Это будет означать добавление:

 * @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"facebook" = "Facebook", "instagram" = "Instagram"})

к моему коду. У меня были большие надежды, но, к сожалению, валидатор дал мне эту ошибку:

[Учение \ ORM \ Mapping \ MappingException] Не поддерживается определение информации о наследовании для сопоставленного суперкласса
s ‘Портал \ SocialMedia \ Entity \ SocialMediaAbstract’.

Суперклассы mame mapper не поддерживаются.

РЕДАКТИРОВАТЬ 2 / ВЫВОД:
Я решил использовать наследование таблиц классов (как и в приведенном ниже ответе). Удаление реферата из класса позволило все еще использовать мою фабрику.

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

Один небольшой комментарий: Менеджер сущностей Doctrine более или менее уже предоставляет Factory:

$socialMedia = $entityManager->find('Portal\SocialMedia\Entity\SocialMedia', 2);

Это возвращает объект Instagram. Я по-прежнему предлагаю вам построить собственную фабрику над ней для удобства обслуживания позже, поскольку сущность SocialMedia может измениться позже.

1

Решение

Некоторое время прошло с тех пор, как я работал с доктриной, но если я правильно помню, Ученые намеченные супер классы являются реализацией тип наследования бетонного стола Мартин Фаулер.

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

Я думаю, что шаблон, который вы ищете, это либо наследование одной таблицы или же наследование таблиц классов (посмотри на типы наследования доктрины).


Наследование одной таблицы реализован в типе наследования доктрины «SINGLE_TABLE», где у вас есть одна таблица для всех сущностей. Они имеют одни и те же атрибуты и один и тот же пул идентификаторов, то есть вы можете «добавить» идентификатор, получить объект и проверить тип (Facebook, Instagram и т. Д.).

Недостатком является то, что если вы получили в любом из предметов, атрибут, который может быть NULL, вы можете столкнуться с проблемами, если другие объекты не имеют этого атрибута или не нуждаются в нем. Это будет означать, что вы должны установить для данного атрибута фиктивное значение в других объектах, чтобы сохранить их в таблице базы данных.


Наследование таблиц классов преодолевает эту проблему, сохраняя каждую сущность в своей собственной таблице, и в то же время может совместно использовать пул идентификаторов, поскольку доктрина заботится о том, чтобы общие атрибуты сохранялись в таблице базовых классов, а все атрибуты, характерные для сущности, сохранялись в таблица сущности. Затем к таблицам присоединяется идентификатор, отсюда и тип наследования «JOINED» в доктрине.


Заключение:

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

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

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

Вы все еще должны иметь возможность использовать SocialMediaFactory с шаблоном наследования таблицы или таблицы классов.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]