2011-01-07 220 views
6

我有一個親子關係。父對象具有許多子對象,並且每個子對象通過引用知道它的父對象。PHP對象父/子遞歸

父母也可以是孩子(基本上它的樹)。

在i根對象上做一個的var_dump()它說[「父」] =>遞推多次並且將所生成的描述將是很長的。

我想知道如果我做錯了什麼。如果是的話,我對「最佳實踐」感興趣。

感謝您的幫助!

+0

一些代碼會很好! – 2011-01-07 15:41:04

+1

聽起來像你在圖中有一個循環(父母也是其後代之一的孩子),但是沒有看到代碼或樣本數據,很難肯定地說。 – FrustratedWithFormsDesigner 2011-01-07 15:41:19

回答

12

你沒有做錯任何事;你有一個家長參考其子女,每個孩子都有一個參考回到其父母。當你對根對象進行迭代時,它遍歷子對象來打印它們,並且由於每個子對象都有對父對象的引用,所以它會返回。因爲這通常會導致一個無限循環(父 - >子 - >父 - >子 - > ...),PHP保留已經訪問的對象的列表,並且當它遇到一個時,它不會嘗試轉儲它再次,但是打印「RECURSION」。

唯一需要注意的是PHP使用引用計數來處理垃圾回收,像這樣的循環結構不能自行解決。因此,您的腳本會泄漏內存,這可能會也可能不會成爲問題。爲了解決這個問題,你需要手動清理:在父對象超出作用域之前,你需要將所有父指針設置爲空。

參見:http://bugs.php.net/bug.php?id=33595

6

var_dump功能走到你的對象圖遞歸和打印對象的所有訪問的數據。現在嘗試把下面的圖表變成純英文。

 has    var_dump: 
Parent ----> Child   "The Parent object has a child object" 
^    |    "That Child object has a Parent Object" 
|______________| has    "That Parent object …" 

如果PHP沒有足夠的智能來檢測這種遞歸,它將無限運行。所以相反,它認識到它已經傾銷了該對象並轉儲了RECURSION。你沒有做錯什麼。

Click here for another explanation

0

你能避免遞歸引用的唯一途徑是建立一個「顛倒樹」,這是唯一有用的就是你想從孩子到父搜索不知道兄弟姐妹時。像:

class Foo { 
    protected $parent; 

    public function __construct(Foo $parent = null) { 
     $this->parent = $parent; 
    } 

    public function getParent() { 
     return $this->parent; 
    } 
} 

$a = new Foo; 
$b = new Foo($a); 
$c = new Foo($b); 

所以,從$c可以跟蹤到根節點,爲$a,沒有遞歸引用。

如果您需要從根節點轉到子節點,那麼沒有其他解決方案比您已經做了,這是正確的。