我正在使用symfony框架在PHP中开发,但问题更广泛地适用于非symfony和非PHP开发人员。 (对于symfony开发人员,我使用单表继承映射使用Doctrine ORM将子类映射到数据库,BasePerson扩展了FOSUserBundle,然后由两个子类进一步扩展。)
“BasePerson”扩展了原来的User类,后者进一步扩展为两个独立的子类:摄影师,PhotoSubject。
拥有子类是一个很好的逻辑分离,但是当我有一个摄影师也是PhotoSubject时会出现问题。他们将共享相同的电子邮件地址,但不同的用户名(在User类中)。
然而现在我有两个对象用于同一个人(同一个用户):一个PhotoSubject和一个摄影师,它们具有不同的用户名和可能不同的密码等,这在Doctrine中显然是不可能的 - 它们需要存储为两个使用不同的用户名分隔DB记录。对同一个用户进行两次不同的登录对我来说似乎是一个设计问题。
有人能为这个问题建议正确的设计吗?我应该不使用继承来避免这个问题,而是有一个没有扩展的单片“BasePerson”类。当用户登录时,我应该以某种方式检查数据库中是否有使用相同电子邮件地址的另一个“人”?或者是否有另一种解决这个问题的方法?
答案 0 :(得分:0)
我认为这里的问题是你混淆了与子类型的关系。
摄影师可能是一种类型的人,只要它不会在相互排他性的情况下引发类似的问题,但是照片主体并不是一种人。
照片主题应该是照片与人之间的关系(1张照片 - >主题/人物)
答案 1 :(得分:0)
我认为你混淆了继承,行为和数据。在这种特殊情况下,我宁愿用接口替换Photographer
和PhotoSubject
类
interface Photographer {
/**
* @param PhotoSubject[] $filter subjects to filter the photos
*
* @return Image[]
*/
public function getPhotos(array $filter);
public function addPhoto(Image $photo);
/** @return Image */
public function shot(PhotoSubject $subject);
// any other methods
}
interface PhotoSubject {
/**
* @return Image[] the images of the subject
*/
public function getSubjectShots();
}
class Person implements Photographer, PhotoSubject {
/** @var Image[]|ArrayCollection */
private $ownImages;
/** @var Image[]|ArrayCollection */
private $referencedShots =[];
public function getPhotos(array $filter) { return $this->ownImages->filter(...)->toArray(); }
public function addPhoto(Image $photo) {
$this->ownImages->add($photo);
$photo->setAuthor($this);
}
public function getSubjectShots() { return $this->referencedShots->toArray(); }
public function shot(PhotoSubject $subject) {
$image = new Image();
$this->addPhoto($image);
$image->addSubject($subject);
return $image;
}
}
你真的不需要为世界上每种类型的对象提供类。您有一个对象 - Person
和界面允许您从不同的角度显示Person
。在物理学中,它被称为"模型" - 简化对象,描述目前所需的参数。同样在这里,绑定到行为(接口),而不是实现。