使用PHP对象设置递归属性是否安全?

I have looked everywhere and can't seem to find an answer. What I'm wondering is if it's safe or good practice to use recursive objects in PHP. To create an object as a property of another object, that contains a property with a reference to the containing object...

<?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
        }
    }

And then use it as follows...

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

I'be just noticed that i've had problems using certain functions such as array_multisort (Specifically "PHP Fatal error: Nesting level too deep - recursive dependency?") when trying to sort an array of objects, and when I use var_dump, it shows some properties as being recursive...

Any help is appreciated

Before PHP 5.3, this could cause a problem. PHP used to do reference counting, and circular references used to keep the object from getting GCed.

Now that 5.3 implements a decent garbage collector, this isn't quite as much of an issue. But passing such objects to any function that traverses the object graph could still cause infinite recursion, if the function isn't aware of the possibility and prepared to handle it. (I think var_dump handles recursion decently, but recursively sorting such objects will probably cause all kinds of trouble.)

Note that bar->database->any_method() won't work because database is private.

When you create a recursive reference to an object in PHP, it's actually pretty good about it -- it just uses the existing reference and apparently doesn't create a lot more memory. In this case, you're not creating a non-deterministic level of recursion -- it's just one set of objects, so an overflow is unlikely unless you're creating tons of these objects (and it would probably be for a different reason).

If you do a var_dump on User, you'll see:

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*
      }
    }
  }
}

...so PHP notices the recursion.

I'd also have to ask why you would do that in this instance.