Php 两个相互依赖类的构造函数注入

Php 两个相互依赖类的构造函数注入,php,oop,Php,Oop,用户填写表单并提交。根据输入,对象组织被水合。我想将与数据库的通信与实际对象分开 我想创建一个OrganizationMapper,它保存数据库通信的方法(保存、删除…)。organization类将通过构造函数获取OrganizationMapper 但是,使用这些类定义,我无法实例化这些类,因为它们相互依赖 否则,我如何将数据库通信与组织分离,并将其放入组织映射器 class Organization { protected $id; protected $name;

用户填写表单并提交。根据输入,对象
组织
被水合。我想将与数据库的通信与实际对象分开

我想创建一个
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...}
}

这就是为什么循环依赖通常被认为是一件坏事


别开玩笑了,在我看来,
OrganizationMapper
类中实际上并不需要构造函数依赖项。从外观上看,您正在将希望作为参数持久化的
组织
实例传递到映射器的
save()
方法中,并且在该类中根本不需要实例属性
$this->Organization

一般来说,我会尽量使组织映射器保持无状态。尽量避免将一个
组织
实例存储为实例属性(特别是当您实际使用同一个映射器实例来持久化多个
组织
时)。只需像使用
save()
方法一样,将
组织
对象作为方法参数传递即可


此外,我不会将
组织
类与映射器相关联。有人可能会争辩说,这违反了规则,因为坚持自己不是类的责任。您可以将此逻辑移到调用代码中,让
组织
类根本不知道映射器(这很好,因为您完全消除了两个类之间的循环依赖):

班级组织
{
受保护的$id;
受保护的$名称;
// 
// 
}
类组织映射器
{
公共功能保存(组织$Organization)
{
//以某种方式将$organization保存到DB
}
}
$organization=新组织();
$organization->setName('Foobar International Inc.);
$mapper=新组织映射器();
$mapper->save($organization);

这就是为什么循环依赖通常被认为是一件坏事


别开玩笑了,在我看来,
OrganizationMapper
类中实际上并不需要构造函数依赖项。从外观上看,您正在将希望作为参数持久化的
组织
实例传递到映射器的
save()
方法中,并且在该类中根本不需要实例属性
$this->Organization

一般来说,我会尽量使组织映射器保持无状态。尽量避免将一个
组织
实例存储为实例属性(特别是当您实际使用同一个映射器实例来持久化多个
组织
时)。只需像使用
save()
方法一样,将
组织
对象作为方法参数传递即可


此外,我不会将
组织
类与映射器相关联。有人可能会争辩说,这违反了规则,因为坚持自己不是类的责任。您可以将此逻辑移到调用代码中,让
组织
类根本不知道映射器(这很好,因为您完全消除了两个类之间的循环依赖):

班级组织
{
受保护的$id;
受保护的$名称;
// 
// 
}
类组织映射器
{
公共功能保存(组织$Organization)
{
//以某种方式将$organization保存到DB
}
}
$organization=新组织();
$organization->setName('Foobar International Inc.);
$mapper=新组织映射器();
$mapper->save($organization);

在php中不能这样做。想象一下,如果可以的话。然后,组织的实例将有一个属性OrganizationMapper,它将有一个属性组织。因此,类实例的属性的属性就是实例本身!它只可能在语言中使用指针,如C++。因此,我在这里只看到两种解决方案:

  • 把课程放在一起
  • 有一个链接(可能有一个类调用另一个,而第二个类不调用第一个。)

    • 在php中无法实现这一点。想象一下,如果可以的话。然后,组织的实例将有一个属性OrganizationMapper,它将有一个属性组织。因此,类实例的属性的属性就是实例本身!它只可能在语言中使用指针,如C++。因此,我在这里只看到两种解决方案:

      • 把课程放在一起
      • 有一个链接(可能有一个类调用另一个,而第二个类不调用第一个。)

      要找到更好的方法来区分这两个问题,请考虑两个对象的用途:

      • 一个组织可以让你访问该组织的所有信息
      • 您的OrganizationMapper用于将组织对象保存到数据库
      当你这样想的时候,就会有几个问题出现:

      • 为什么您的组织需要saveToDb()方法?救它不是我的工作吗
      • OrganizationMapper的实例应该能够保存数据库中的任何组织,那么为什么要将其传入两次呢?(一次在构造函数中,一次在save($organization)方法中)。在这种情况下,如果将不同的组织传递给构造函数而不是save方法,会发生什么?
        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);