(PHP)从类代码中取消设置对象

Is it possible to unset (clean or un-instantiate) an object of a class by executing code of that particular class?

My scenario is one that, for some reason, I reach a point that the object has no meaning to exist anymore, so I want to make sure that is will not be used again by killing its reference in memory.

Here is a snippet example:

class Foo {
    public $bar = "doh!";
    function destroy() {
        // ???    
    }
}
$o = new Foo();
echo $o->bar . '
';
$o->destroy();
echo $o->bar . '
'; // I expect an error here...

If I do a "unset" command outside the class code, it works, obviously:

$o = new Foo();
unset($o);
echo $o->bar . '
'; // PHP Notice:  Undefined property: Foo::$bar in ...

But I tried to do it inside the "destroy" method, by calling "unset", or creating a custom "__destruct", but none worked.

Any ideas are very welcome.

Cheers,

Yeah, it seems impossible to achieve... another dirty way could be:

class Foo {
    public $bar = "doh!";
    function destroy() {
        unset($this->bar); // and do this for EVERY property of this class
    }
}
$o = new Foo();
echo $o->bar . '
';
$o->destroy();
echo $o->bar . '
'; // PHP Notice:  Undefined property: Foo::$bar in...

However, the object would still exists, and methods would still be accessible.

What's wrong with unset($o)? You could wrap that behaviour up in a static class method if it really offends you:

class Foo {
    public static function destroy(&$foo) {
        unset($foo);
    }
}
Foo::destroy($o);

Take into account that you can't explicitly destroy an object.

The ways to allow PHP Garbage Collector to act upon an object are:

$var = null; // set to null
unset($var); // unset

The object will stay there. However, if you unset the object and your script pushes PHP to the memory limits, the objects not needed will be garbage collected. I would go with unset() as it seams to have better performance (not tested but documented on one of the comments from the PHP official manual).

That said do keep in mind that PHP always destroys the objects as soon as the page is served. So this should only be needed on really long loops and/or heavy intensive pages.

It's impossible. You can unset a variable or set it to null but there's no guarantee that you won't have any references to this object ($b = $o; $b won't be destroyed with unset($o);).

An ugly solution is add a field in your class, e.g. destroyed, check in every method that it's not true and throw an exception if it is.

Since php 5.2, it's possible using spl_object_hash but it shouldn't be used...

class MyClass {
    public function destroy(){
        foreach($GLOBALS as $k => $v){
            // bucabay is totally right ! It's faster this way
            //if(is_object($v) && (spl_object_hash($v) == spl_object_hash($this))){
            if($v === $this){
                    $GLOBALS[$k] = null;
                    return;
            }
        }
    }
}
$a = new MyClass;
$b = new MyClass;

var_dump($a, $b); // class MyClass#1 (0) {}class MyClass#2 (0) {}
echo "
";

$a->destroy();
var_dump($a, $b); // NULL class MyClass#2 (0) {}
echo "
";

$b->destroy();
var_dump($a, $b); // NULL NULL

You can use:

public function delete()
    {
        foreach($GLOBALS as $name => $value) {
            if ($GLOBALS[$name] === $this) {
                unset($GLOBALS[$name]);
            }
        }
    }

any PHP version. This only works if the object is in the global scope.