Итак, я наткнулся на это препятствие, когда мне нужно создать абстрактный класс и фабрику для создания объектов более определенных классов, которые расширяют абстрактный класс и реализуют более конкретные методы объекта.
Проще говоря, я получил класс 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 может измениться позже.
Некоторое время прошло с тех пор, как я работал с доктриной, но если я правильно помню, Ученые намеченные супер классы являются реализацией тип наследования бетонного стола Мартин Фаулер.
В приведенном там примере Player
является сопоставленным суперклассом, атрибуты которого распространяются на все наследуемые объекты / модели. Дело в том, что игрок не может быть создан и, следовательно, не имеет собственного идентификатора. Вместо этого у каждой модели наследования есть свой собственный идентификатор, который не зависит друг от друга.
Я думаю, что шаблон, который вы ищете, это либо наследование одной таблицы или же наследование таблиц классов (посмотри на типы наследования доктрины).
Наследование одной таблицы реализован в типе наследования доктрины «SINGLE_TABLE», где у вас есть одна таблица для всех сущностей. Они имеют одни и те же атрибуты и один и тот же пул идентификаторов, то есть вы можете «добавить» идентификатор, получить объект и проверить тип (Facebook, Instagram и т. Д.).
Недостатком является то, что если вы получили в любом из предметов, атрибут, который может быть NULL
, вы можете столкнуться с проблемами, если другие объекты не имеют этого атрибута или не нуждаются в нем. Это будет означать, что вы должны установить для данного атрибута фиктивное значение в других объектах, чтобы сохранить их в таблице базы данных.
Наследование таблиц классов преодолевает эту проблему, сохраняя каждую сущность в своей собственной таблице, и в то же время может совместно использовать пул идентификаторов, поскольку доктрина заботится о том, чтобы общие атрибуты сохранялись в таблице базовых классов, а все атрибуты, характерные для сущности, сохранялись в таблица сущности. Затем к таблицам присоединяется идентификатор, отсюда и тип наследования «JOINED» в доктрине.
Заключение:
использование наследование одной таблицы если классы очень похожи и отличаются только определением или реализацией функции, но имеют одинаковые атрибуты.
использование наследование таблиц классов если классы имеют разные атрибуты, которые было бы проблематично хранить в одной таблице.
использование наследование конкретного стола если классы на самом деле не связаны друг с другом, а имеют только небольшое количество общих атрибутов. Но это также может быть реализовано через Черты PHP, который, по моему мнению, проще и более гибок в использовании, чем отображенный в доктрине суперкласс. В признаке PHP вы также можете использовать аннотации доктрины, потому что интерпретатор PHP правильно назначит аннотации классам, в которых вы используете признаки.
Вы все еще должны иметь возможность использовать SocialMediaFactory с шаблоном наследования таблицы или таблицы классов.
Других решений пока нет …