2

我到处寻找,似乎找不到答案。我想知道的是在 PHP 中使用递归对象是否安全或良好的做法。要将对象创建为另一个对象的属性,该对象包含一个引用包含对象的属性...

<?php

    class User
    {
        public $database;

        public function __construct() {
            $this->database = new Database($this);
        }
    }

    Class Database
    {
        private $user;

        public function __construct(User $user) {
            $this->user = $user;
        }

        public function doSomethingForUser() {
            // Call db or get info for this user
        }
    }

然后按如下方式使用它...

    <?php
        $bar = new User();
        $bar->database->doSomethingForUser();
    ?>

我只是注意到在尝试对对象数组进行排序时,我在使用某些函数时遇到了问题,例如 array_multisort(特别是“PHP 致命错误:嵌套级别太深 - 递归依赖?”),当我使用 var_dump 时,它显示一些属性是递归的......

任何帮助表示赞赏

4

2 回答 2

4

在 PHP 5.3 之前,这可能会导致问题。PHP 用于进行引用计数,循环引用用于防止对象被 GC。

现在 5.3 实现了一个像样的垃圾收集器,这不是什么大问题。但是,如果函数没有意识到这种可能性并准备好处理它,那么将这些对象传递给遍历对象图的任何函数仍然可能导致无限递归。(我认为var_dump可以很好地处理递归,但是递归排序这些对象可能会导致各种麻烦。)

于 2012-05-02T00:34:08.690 回答
1

请注意,这bar->database->any_method()不起作用,因为database它是私有的。

当您在 PHP 中创建对对象的递归引用时,它实际上非常好——它只是使用现有的引用并且显然不会创建更多的内存。在这种情况下,您并没有创建一个不确定的递归级别——它只是一组对象,因此除非您创建大量这些对象(并且可能出于不同的原因),否则不太可能发生溢出.

如果您执行var_dumpon User,您将看到:

object(User)#1 (1) {
  ["database:private"]=>
  object(Database)#2 (1) {
    ["user:private"]=>
    object(User)#1 (1) {
      ["database:private"]=>
      object(Database)#2 (1) {
        ["user:private"]=>
        *RECURSION*
      }
    }
  }
}

...所以 PHP 注意到递归。

我还不得不问为什么在这种情况下你会这样做。

于 2012-05-02T00:34:32.920 回答