Есть два класса, в одном создаётся другой, и другому передаётся по ссылке первый. Он у себя это запоминает. Потом пытюсь уничтожить первый класс командой unset . Класс пропадает, становится NULL и должен якобы пропасть класс который был создан внутри. Но вот функция __destruct отрабатывается, только тогда, когда скрипт заканчивает работу. То есть остаётся где-то копия данного класса, к которой я не могу получить доступ. Вопрос. Как нормально уничтожать такие объекты, чтобы отрабатывался __destruct. И все копии сколько их бы не было уничтожались. Вот на этом коде проводил тестирование. PHP: <?php class A{ public $parent_class; public function add_parent(&$class){ echo "Add parent class\n"; $this->parent_class = &$class; } public function __construct(){ echo "Construct Class A\n"; } public function __destruct(){ echo "Desctruct class A\n"; } } class B{ public $one_class; public function test(){ $this->one_class = new A; $this->one_class->add_parent(&$this); } public function __construct(){ echo "Construct Class B\n"; } public function __destruct(){ echo "Desctruct class B\n"; } } echo "init class B\n"; $test_cl = new B(); echo "run test func\n"; $test_cl->test(); echo "try unset B\n"; unset($test_cl); echo "now this class='".var_export($test_cl, true)."' \n"; echo "end script\n"; ?> Вывод дает следующий init class B Construct Class B run test func Construct Class A Add parent class try unset B now this class='NULL' end script Desctruct class B Desctruct class A Получается что объект $test_cl после unset сталл равен NULL. Но при этом в памяти где-то висит копия и как я понимаю занимает место.
Что-то я не понимаю, как можно уничтожить класс и создать в классе другой класс... Может здесь всё заменить на "объекты класса"?
Какие умные ответы, я аж плакал, особенно про мозги и проектирование. 2Clone Ну сформулировала неправильно, бывает.
- зачем вообще дается возможность самому писать деструкторы? - каким образом что-то еще может получить ссылку на объект внутри какого-то объекта?
PHP: <?php class B{ private $just_a_var; public function test($var){ $var = strrev($var); $global_c->just_a_var = $var; //echo "Test var='".$var."' \n"; return $var; } public function __construct($name){ $this->name = $name; echo "Construct Class B name='".$this->name."'\n"; } public function __destruct(){ echo "Desctruct class B name='".$this->name."'\n"; } } class D{ public $s_class; public function add_class(&$class){ $this->s_class = &$class; } public function test($var){ $var = strtoupper($var); return $this->s_class->test($var); } public function __construct($name){ $this->name = $name; echo "Construct Class D name='".$this->name."'\n"; } public function __destruct(){ echo "Desctruct class D name='".$this->name."'\n"; } } echo "construc class B\n"; $test_cl = new B('name_one'); echo "construc class D\n"; $test_D = new D('name_two'); echo "add in class D class B\n"; $test_D->add_class(&$test_cl); echo "run func from D\n"; $ret = $test_D->test('abc'); echo "return ret='".$ret."' \n"; echo "Try unset class B\n"; unset($test_cl); echo "Try unset class D\n"; unset($test_D); echo "End Programm\n"; ?> вывод php -q test11.php construc class B Construct Class B name='name_one' construc class D Construct Class D name='name_two' add in class D class B run func from D return ret='CBA' Try unset class B Try unset class D Desctruct class D name='name_two' Desctruct class B name='name_one' End Programm Покаместь D не будет убит С тоже не освободится. Это просто пример на коленке. И разговор идёт не об алгоритме и проектировке, а именно о ссылках к объектам. И каким образом полностью уничтожать объект.
mrsol, пока в пхп не появится сборщика мусора учитывающего циклические сылки (а это тормоза) - связи объекта с другими нужно разрывать вручную.
Или ещё код. Наследования самого себя. PHP: <?php class B{ private $child_class; private $name; public function add_children(&$class, $counter){ $t_counter = $counter; echo "Add child class counter='".$counter."' \n"; if($counter<=0){ echo "Exit by counter\n"; return true; } $this->child_class = &$class; $counter--; $this->child_class->add_children($class, $counter); echo "End add child class couner='".$t_counter."' \n"; } public function __construct($name, $count_child = 5){ $this->name = $name; echo "Construct Class B name='".$this->name."'\n"; $this->add_children(&$this, $count_child); } public function __destruct(){ echo "Desctruct class B name='".$this->name."'\n"; } } echo "Init class\n"; $test_cl = new B('name_one', 3); echo "Try unset\n"; unset($test_cl); echo "Now variable is='".var_export($test_cl, true)."' \n"; echo "Try init second class for this variable\n"; $test_cl = new B('name_two', 3); echo "Try unset second\n"; unset($test_cl); echo "Now variable is='".var_export($test_cl, true)."' \n"; echo "End programm\n"; ?> Показывает php -q test12.php Init class Construct Class B name='name_one' Add child class counter='3' Add child class counter='2' Add child class counter='1' Add child class counter='0' Exit by counter End add child class couner='1' End add child class couner='2' End add child class couner='3' Try unset Now variable is='NULL' Try init second class for this variable Construct Class B name='name_two' Add child class counter='3' Add child class counter='2' Add child class counter='1' Add child class counter='0' Exit by counter End add child class couner='1' End add child class couner='2' End add child class couner='3' Try unset second Now variable is='NULL' End programm Desctruct class B name='name_one' Desctruct class B name='name_two' После первого унсета, доступа к этому классу у меня нет, так как ссылка на объект является NULL. Ещё раз создаю ссылку на объект на этой переменно и опять её убиваю. Итого у меня подвешано два объекта, к которым никак нельзя получить доступ. И будут висеть, до тех пор пока не закончит работу скрипт. Так до него дело и не доходит. Вернее доходит, но не тогда когда надо.
Сборщик мусора не будет вызываться до тех пор пока достаточно памяти, чтобы не было бесполезного overheading-a.
Знаете есть такое дерево. Фиг вам. mem='134,128,832' Init class xo='2753' Construct Class B name='name_one 2753' Add child class counter='2' Add child class counter='1' Add child class counter='0' Exit by counter End add child class couner='1' End add child class couner='2' Try unset Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 40961 bytes) in /home/slavik/sol/autonomic_sms_and_ussd/1/tested/test12.php on line 89 2dark-demon А что использовать? Я не говорю что мне нужен именно unset
mrsol Где-то я раньше читал что unset нельзя делать, попробуй просто обнулять указатели на объект. $blabla = new Blabla(); $blabla = null;
Как я unlink собственная функция, в которой проверяются и рвутся исходящие связи. Как это реализовать? Правильно, при этом раскладе просто обнуляется связь на объект. И объект остается в свободном плавание. Щас приведу другой пример.
Вот пример с внутренней рекурсией. И с использованием register_tick_function. Создаеться первый объект в котором происходит регистрация функции. И пытаюсь сделать unset. Потом создаю второй объект и пытаюсь приравнять к NULL. Результат один и тот-же. PHP: <?php class B{ private $child_class; private $name; private $memory; public function add_children(&$class, $counter){ $t_counter = $counter; echo "Add child class counter='".$counter."' \n"; if($counter<=0){ echo "Exit by counter\n"; return true; } $this->child_class = &$class; $counter--; $this->child_class->add_children($class, $counter); echo "End add child class couner='".$t_counter."' \n"; } public function __construct($name, $count_child = 5){ $this->name = $name; echo "Construct Class B name='".$this->name."'\n"; $this->add_children(&$this, $count_child); register_tick_function('eche_ticks', $this->name); declare(ticks=1); } public function __destruct(){ echo "Desctruct class B name='".$this->name."'\n"; unregister_tick_function('eche_ticks'); } } function eche_ticks($name){ ///to do somthing at each ticks echo "---------------Ticks name='".$name."' \n"; } declare(ticks=1); echo "Init \n"; $test_cl = new B('name_one', 1); echo "Try unset\n"; unset($test_cl); echo "Now variable is='".var_export($test_cl, true)."' \n"; echo "Init \n"; $test_cl = new B('name_two', 1); echo "Try NULL\n"; $test_cl = NULL; echo "Now variable is='".var_export($test_cl, true)."' \n"; for($x=1; $x<=3; $x++){ echo "x='".$x."'\n"; } echo "end script\n"; ?> Результат Код (Text): php -q test13.php Init Construct Class B name='name_one' Add child class counter='1' Add child class counter='0' Exit by counter End add child class couner='1' ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_one' Try unset ---------------Ticks name='name_one' ---------------Ticks name='name_one' Now variable is='NULL' ---------------Ticks name='name_one' Init ---------------Ticks name='name_one' Construct Class B name='name_two' Add child class counter='1' Add child class counter='0' Exit by counter End add child class couner='1' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' Try NULL ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' Now variable is='NULL' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' x='1' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' x='2' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' x='3' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' end script ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' Desctruct class B name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_one' ---------------Ticks name='name_two' Desctruct class B name='name_two' ---------------Ticks name='name_two' Тики всё равно идут. До конца скрипта. Если в строках 42 и 48 $test_cl = new B('name_one', 1); и $test_cl = new B('name_two', 1); Заменить 1 на 0 То получается следующий результат Код (Text): php -q test13.php Init Construct Class B name='name_one' Add child class counter='0' Exit by counter ---------------Ticks name='name_one' ---------------Ticks name='name_one' ---------------Ticks name='name_one' Try unset ---------------Ticks name='name_one' Desctruct class B name='name_one' ---------------Ticks name='name_one' Now variable is='NULL' Init Construct Class B name='name_two' Add child class counter='0' Exit by counter ---------------Ticks name='name_two' ---------------Ticks name='name_two' ---------------Ticks name='name_two' Try NULL ---------------Ticks name='name_two' Desctruct class B name='name_two' ---------------Ticks name='name_two' Now variable is='NULL' x='1' x='2' x='3' end script Как и должно было работать. И unset и NULL ведут себя идентично.
PHP: function unlink( ){ var $vars= get_object_vars( $this ); foreach( $vars as $name => &$val ) unset( $this->$name ); } типа того