Page 1 of 1

destroying objects

Posted: Sat Aug 19, 2006 11:10 pm
by daedalus__
I'm trying to use this function to destroy objects.

It doesn't work but I do not know why.

I would like it to work but do not know how to make it work.

Can I not use references like that?

:(

Code: Select all

function Destroy(&$object)
{
	if ( is_object($object) )
	{
		unset($object);
	}
}

Posted: Sat Aug 19, 2006 11:22 pm
by feyd
You're working in PHP 5 right? Objects are passed by reference already.

And unset() is all you need.

Posted: Sat Aug 19, 2006 11:31 pm
by daedalus__
Well, I have this service locator. It stores objects in an array like TNSG's does. I figured that I may want to remove an object from that array for some reason (maybe i only need it for a second) so I put that function in there.

So, I say something like this:

Code: Select all

$wrapper->destroy($wrapper->objects['test']);
I thought that, $wrapper->objects['test'] would be destroyed but it isn't.

I could just pass the keyname of the object and do it that way but I wanted to know if it would work when i referenced the object.

Posted: Sat Aug 19, 2006 11:37 pm
by feyd
PHP uses reference counting. If further references exist to the object, PHP will not destroy it.

Posted: Sat Aug 19, 2006 11:46 pm
by daedalus__
Is there that I can find all the references or something?

I'm just going to pass it the object name I guess, but I would still like to know.

Posted: Sat Aug 19, 2006 11:52 pm
by feyd
I don't believe there is a way. However, you could set an internal property that tells other instances to stop reacting and/or directly call the __destruct() method. If your class methods are built right, having the destructor called would short circuit them from processing things further.

Posted: Sun Aug 20, 2006 12:01 am
by daedalus__
I don't know if this is what you meant but I tried:

Code: Select all

function destroy($object)
{
    $object->__destruct();
}
I had to add a __destruct() method to the class as well.

Might you be able to show an example of what you mean?

Posted: Sun Aug 20, 2006 12:08 am
by feyd
Yes, that is what I was talking about. The method would normally be called by PHP during actual destruction, but since you want to basically force destruction, you need to call it yourself and in some way short circuit any calls to other references to the object to, basically, self destruct as well.

Posted: Sun Aug 20, 2006 12:17 am
by daedalus__
feyd wrote:in some way short circuit any calls to other references to the object to, basically, self destruct as well.
I'm having trouble understanding that because it should only exist in one place, and is not being used in the script anywhere other than the service locator.

Could this bit of code be making destructing it tricky?

Code: Select all

$this->object = $this->Instantiate($class_name, $args);
$this->objects[$object_name] = $this->object;
unset($this->object);
It's the only thing I can think of?

Posted: Sun Aug 20, 2006 12:34 am
by daedalus__
I'm just going to go ahead and pass the name of the object rather than a reference. It works.

It really bugs me that passing a reference isn't working though. I'd really like to figure it out. :P

Posted: Sun Aug 20, 2006 12:35 am
by feyd
When $this->objects[$object_name] is passed into destroy() you will effectively have two references to the object. Calling unset() will only destroy the local reference. However, if you set it to null, false, or something else you will overwrite the originally passed reference too. An example:

Code: Select all

[feyd@home]>php -r "$arr = array(); class foo{} $foo = new foo(); $arr[] = $foo; function nil(&$o){$o = null;} var_dump($arr,$foo); nil($arr[0]); var_dump($arr,$foo);"
array(1) {
  [0]=>
  object(foo)#1 (0) {
  }
}
object(foo)#1 (0) {
}
array(1) {
  [0]=>
  NULL
}
object(foo)#1 (0) {
}
Notice that the original object still exists because $foo has not been destroyed.

Posted: Sun Aug 20, 2006 12:37 am
by daedalus__
So, set the reference to null or some other value and then destroy it?

Posted: Sun Aug 20, 2006 12:45 am
by feyd
Setting the reference to null or whatever effectively destroys the object by removing two references to it at once, but any further references will still hold the object untouched as I've said and shown before.

Posted: Sun Aug 20, 2006 12:46 am
by daedalus__
I guess that I am not understanding. I didn't understand the debugging thing you posted either.

I am going to work with it more tomorrow. :D
I'm tired.

Posted: Sun Aug 20, 2006 5:18 am
by volka
Each object (amongst others) has a reference counter.
$obj = new MyClass(), new object, assigned to a variable, reference counter=1 (slightly simplified ;))
$o = $obj; increments that counter for the object $obj is pointing to, because $o is a new reference, counter=2
$obj = null;, one reference eliminated, reference counter 1. There's still a way to access the object.
$o = null; another reference is removed, reference counter 0, i.e. there's no way to reference that object anymore. php can and will collect the garbage.

not strictly but generally related: http://www.iecc.com/gclist/GC-faq.html