【问题标题】:Prevent Object recursion/loop by reference in PHP通过 PHP 中的引用防止对象递归/循环
【发布时间】:2020-02-25 20:21:43
【问题描述】:

还没有找到答案,但我确信一定有一个:当对象相互引用时,如何防止对象递归/循环?一个例子:

class Patient {
    private $Issues = array();

    [...]

    public function __construct($id) {
        [ Get data from DB ]
        while ($row = $result->fetch_assoc()) {
            $this->Issues[$row['idIssue']] = new Issue($row['idIssue']);
        }
        [...]
    } 
}

class Issue {
    private $Patient;

    [...]

    public function __construct($id) {
        [ Get data from DB ]
        $this->Patient = new Patient($row['idPatient']); <-- Leads to recursion as the patient will load all it's Issues() etc. etc.
        [...]
    }
}

如何防止这种情况发生?我可以使用 Patient() 的 id 而不是真实对象,但这感觉就像是 hack。有没有办法使用实物?

【问题讨论】:

  • Issue 构造函数采用Patient 实例吗?但是,具有循环依赖关系通常被认为是一种反模式。这个问题绝对需要了解患者吗?
  • 谢谢,这就是下面的建议。问题不一定需要了解患者,但我有其他课程需要了解彼此。

标签: php loops object recursion reference


【解决方案1】:

您可以(应该!)将数据库连接/查询与实体定义分开并传递对关系的引用,否则,您无法模拟实体,而且混合数据库连接和实体定义违反了separation of concerns

// somewhere in your code
$idPatient = 42;
$patient = new Patient();
$patient->setId($idPatient);

// get datas from DB
while ($row = $result->fetch_assoc())
{
    $issue = new Issue();
    $issue->setId($row['idIssue'])
          ->setPatient($patient);

    $patient->addIssue($issue);

    // or, shorter way :
    // $patient->addIssues((new Issue())->setId($row['idIssue'])
    //                                  ->setPatient($patient));
}

class Patient {
    private $Issues = array();
    private $Id;

    public function addIssue(Issue $issue): self
    {
        $this->Issues[] = $issue;

        return $this;
    }

    public function setId(int $id): self
    {
        $this->Id = $id;

        return $this;
    }
}

class Issue {
    private $Patient;
    private $Id;

    public function addPatient(Patient $patient): self
    {
        $this->Patient = $patient;

        return $this;
    }

    public function setId(int $id): self
    {
        $this->Id = $id;

        return $this;
    }

}

【讨论】:

  • 谢谢你的建议,我明白你的观点和它的优雅。然而,对我来说,保持 PHP 对象和 DB 模型同步会使代码更具可读性。
  • 这是一种不好的做法。如果您在构造函数中查询数据库,则无法创建假对象,也无法创建尚未在数据库中的新对象
  • 如果您在某些天使用诸如 Doctrine 之类的 ORM,您的实体将是这样的,并且 DB 内容将与实体定义分开
【解决方案2】:

不要重新创建对象。只需将 master 对象的实例传递给 detail 构造函数。例如:

class Patient {
    private $Issues = array();

    [...]

    public function __construct($id) {
        [ Get data from DB ]
        while ($row = $result->fetch_assoc()) {
            $this->Issues[$row['idIssue']] = new Issue($row['idIssue'], $this);
        }
        [...]
    } 
}

class Issue {
    private $Patient;

    [...]

    public function __construct($id, Patient $patient) {
        [ Get data from DB ]
        $this->Patient = $patient
        [...]
    }
}

【讨论】:

  • 谢谢,这就是我要找的!但是有一个问题:“Patient”对象不应该通过引用传递(以节省内存/执行时间)吗?像这样:public function __construct($id, Patient &amp;$patient) { [ Get data from DB ] $this-&gt;Patient = &amp;$patient [...] }
  • 他的例子就是这种情况。对象已经作为引用传递。检查这个fiddle
猜你喜欢
  • 2017-07-18
  • 2021-05-09
  • 2019-06-23
  • 1970-01-01
  • 2019-06-05
  • 2011-12-12
  • 2015-04-22
  • 2013-08-25
  • 2018-09-06
相关资源
最近更新 更多