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 Fatal error: Nesting level too deep - recursive dependency?」) などの特定の関数を使用すると問題が発生したことに気付きました。また、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 でオブジェクトへの再帰参照を作成すると、実際にはかなりうまくいきます。つまり、既存の参照を使用するだけで、明らかに多くのメモリを作成しません。この場合、非決定論的なレベルの再帰を作成しているわけではありません。オブジェクトのセットは 1 つにすぎないため、これらのオブジェクトを大量に作成しない限り、オーバーフローは発生しません (おそらく別の理由によるものです)。 .

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 に答える