Кажется, я припоминаю способ настроить __destruct
для класса таким образом, чтобы циклические ссылки очищались, как только внешний объект выходит из области видимости. Однако простой тест, который я построил, похоже, указывает на то, что он ведет себя не так, как я ожидал/надеялся.
Есть ли способ настроить мои классы таким образом, чтобы PHP правильно их очищал, когда самый внешний объект выходит за рамки?
Я не ищу альтернативные способы написания этого кода, я ищу, можно ли это сделать, и если да, то как? Обычно я стараюсь избегать циклических ссылок такого типа, где это возможно.
class Bar {
private $foo;
public function __construct($foo) {
$this->foo = $foo;
}
public function __destruct() {
print "[destroying bar]\n";
unset($this->foo);
}
}
class Foo {
private $bar;
public function __construct() {
$this->bar = new Bar($this);
}
public function __destruct() {
print "[destroying foo]\n";
unset($this->bar);
}
}
function testGarbageCollection() {
$foo = new Foo();
}
for ( $i = 0; $i < 25; $i++ ) {
echo memory_get_usage() . "\n";
testGarbageCollection();
}
Вывод выглядит следующим образом:
60440
61504
62036
62564
63092
63620
[ destroying foo ]
[ destroying bar ]
[ destroying foo ]
[ destroying bar ]
[ destroying foo ]
[ destroying bar ]
[ destroying foo ]
[ destroying bar ]
[ destroying foo ]
[ destroying bar ]
На что я надеялся:
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
60440
[ destorying foo ]
[ destorying bar ]
ОБНОВЛЕНИЕ:
Есть несколько отличных ответов на этот вопрос, касающихся PHP> 5.3, но я выбрал ответ, который будет работать с PHP ‹ 5.3, поскольку он действительно относится к моему проекту (PHP 5.2.x).