Така че се натъкнах на това препятствие, при което трябва да създам абстрактен клас и фабрика, за да създам обекти от по-специфични класове, които разширяват абстрактния клас и прилагат по-специфични обектни методи.
Просто казано, имам клас SocialMediaAbstract. Разширяващите класове са Facebook, Instagram и имплементират SocialMediaInterface. Facebook, Instagram и т.н. всички се записват в db, с идентификатор, име и още няколко свойства, които се използват сред разширяващите се класове, следователно един абстрактен клас.
Тъй като искам да мога да правя заявки за няколко неща от обектите на социалните медии и всяка социална медийна платформа има свои собствени API за нея, направих интерфейса и създадох различните класове, така че всички те да могат да имат свои собствени реализации на тези методи.
Сега проблемът, разбира се, е с моя абстрактен клас и доктрина. Doctrine казва това на техния уебсайт по отношение на наследството:
Картографиран суперклас не може да бъде обект, не може да се прави заявка [...]
Сега, ако имах SocialMediaFactory и хвърлих ID, бих искал да получа обратно съответния обект от, например, клас Facebook или Instagram. Не искам да знам коя точно социална медия е, когато ги събирам. Това е проблем с доктрината, поне така мисля.
Пропускам ли нещо, фабричният модел все още ли е възможен? Или наистина трябва просто да премахна абстрактния клас и да създам фабрика, която търси във всяка таблица на клас за внедряване на SocialMediaInterface, което изглежда изключително неефективно и неподлежащо на поддръжка, когато приложението стане по-голямо.
Всякакви идеи или насоки ще бъдат оценени, тъй като съм сигурен, че този проблем трябва да се е появявал по-често. Опитах да потърся в Google и в самия Stackoverflow, но не можах да получа подходящи въпроси или отговори.
Благодаря много предварително.
РЕДАКТИРАНЕ: Попаднах на тази интересна възможност: Наследяване на класова таблица. Това би означавало добавяне на:
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"facebook" = "Facebook", "instagram" = "Instagram"})
към моя код. Имах големи надежди, но за съжаление валидаторът ми даде тази грешка:
[Doctrine\ORM\Mapping\MappingException] Не се поддържа дефиниране на информация за наследяване на картографиран суперклас 'Portal\SocialMedia\Entity\SocialMediaAbstract'.
Суперкласовете на shame mapper не се поддържат.
РЕДАКТИРАНЕ 2/ЗАКЛЮЧЕНИЕ: Реших да използвам наследяване на Class Table (точно както предлага отговорът по-долу). Премахването на резюмето от класа направи възможно все още да използвам моята фабрика.
Сега обаче използвам конкретен клас като абстрактен клас, което се чувства погрешно. Документирал съм в docblock, че не трябва да се създават обекти от този клас.
Една малка странична бележка: Entity Manager на Doctrine повече или по-малко вече предоставя Factory:
$socialMedia = $entityManager->find('Portal\SocialMedia\Entity\SocialMedia', 2);
Това връща обект на Instagram. Все още предлагам да изградите своя собствена фабрика над него за поддръжка по-късно, тъй като обектът на SocialMedia може да се промени по-късно.
@MappedSuperclass
, ако искатеclass table inheritance
. Вече не ви трябва, това е за различен модел на наследяване, вижте отговора ми за обяснение :) - person SaSchu   schedule 28.07.2015