用户填写表单并提交。根据输入,对象Organization
是水合的。我想将数据库与实际对象的通信分开。
我想创建一个OrganizationMapper
来保存数据库通信的方法(保存,删除...)。组织类将通过构造函数获得OrganizationMapper
。
但是,通过这些类定义,我无法实例化类,因为它们相互依赖。
我如何将数据库通信与Organization
分开并将其放入OrganizationMapper
?
class Organization
{
protected $id;
protected $name;
... other properties ...
public function __construct(OrganizationMapper $mapper)
{
$this->mapper = $mapper;
}
public function getId() {...}
public function setId($id) {...}
... other methods ...
public function saveToDb()
{
$this->mapper->save($this);
}
OrganizationMapper
是
class OrganizationMapper
{
public function __construct(Organization $organization)
{
$this->organization = $organization
}
... other methods
public function save($organization)
{... the code to use the methods of Organization class to save the data to the database...}
}
答案 0 :(得分:3)
这就是为什么循环依赖通常被认为是坏事。
除了开玩笑,在我看来,你实际上并不需要OrganizationMapper
类中的构造函数依赖项。从它的外观来看,您将要保留的Organization
实例作为参数传递到映射器的save()
方法中,并且不应该需要该实例该类中的属性$this->organization
。
一般情况下,我会尝试保留OrganizationMapper
无状态。尽量避免将Organization
实例存储为实例属性(尤其是,如果您实际使用相同的映射器实例来保存多个Organization
)。就像您使用save()
方法一样,并将Organization
对象作为方法参数传递。
另外,我不会将Organization
类与映射器关联起来。有人可能会认为这违反了Single Responsibility Principle,因为它不属于班级'坚持自己的责任。您可以将此逻辑移动到调用代码,让Organization
类完全不知道映射器 (这很好,因为您完全取消了循环两个类之间的依赖关系):
class Organization
{
protected $id;
protected $name;
// <other properties here>
// <getters and setters here>
}
class OrganizationMapper
{
public function save(Organization $organization)
{
// save $organization to DB, somehow
}
}
$organization = new Organization();
$organization->setName('Foobar International Inc.');
$mapper = new OrganizationMapper();
$mapper->save($organization);
答案 1 :(得分:2)
要找到更好的方法来分离这两个问题,请考虑两个目标的目的:
当你这样想的时候,会有一些问题出现:
作为替代方案,我建议完全从 Organization 中删除 saveToDb(),因为它不是将自己保存到数据库的组织工作。另外,我会从 OrganizationMapper 中删除当前的构造函数。在它的当前设计中,没有理由将组织传递给构造函数。 另外,我会将OrganizationMapper重命名为OrganizationRepository或OrganizationService。该类的主要目的不是将SQL映射到对象,而是从/向DB检索/保存组织。 (另外,在OOP中,类应该只遵循单一的责任模式,因此SQL和Objects之间的部分映射可能会在专门的类中发生)
作为旁注:一般来说,提供多种方法来完成同样的事情(例如,保存组织)并不是一个好主意。这可能只会导致一段时间的不一致(考虑到将来会添加一些验证逻辑,但可能会忘记在第二位添加它)。
我希望这可以帮到你:)
答案 2 :(得分:1)
免责声明:我在此帖子中将您的Organization
类型命名为OrganizationEntity
。
非常简单,反之亦然。
OrganisationMapper
获取OrganisationEntity
个对象并通过您可以选择的方式将其保留在您想要的任意位置。
对于你的问题:
将saveToDb()
方法从OrganisationEntity
移至OrganisationMapper
,并将其传递给要保存的对象。
答案 3 :(得分:1)
我不知道为什么Mapper会对数据库执行任何操作? Mapper听起来像将实体(组织)转换为可以作为DB操作输入的东西,即。 Query Object。 您应该将班级重命名为DAO或Repository。这会是更好的名字。
恕我直言,最好的想法是:答案 4 :(得分:0)
你不能在php中这样做。想象一下,如果它是posibble。然后,组织实例将拥有一个属性OrganizationMapper,该属性具有属性Organization。因此,类实例的属性的属性将是实例本身!它只能用于像c ++这样的指针语言。所以,我在这里只看到两个解决方案: