Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What determines when a class object is destroyed in PHP?

Let's say that we have class CFoo. In the following example when is CFoo::__destruct() called?

function MyPHPFunc()
{
  $foo = new CFoo();

  . . .

  // When/where/how does $foo get destroyed/deleted?
}

In this example would the destructor be called when the script exits the scope of MyPHPFunc because $foo would no longer be accessible?

like image 837
Jim Fell Avatar asked Dec 15 '11 16:12

Jim Fell


People also ask

What is used to destroy the value of object in PHP?

PHP Destructor: PHP Destructor method is used to destroy objects or release their acquired memory. A destructor is called automatically when the object is created. Usually, it is called at end of the script. The destructor method does not take any arguments, The destructor does not return any data type.

How do you destroy an instance of a class in PHP?

An object is an instance of a class. Using the PHP unset() function, we can delete an object. So with the PHP unset() function, putting the object that we want to delete as the parameter to this function, we can delete this object.

How does PHP remove unused objects?

PHP has a garbage collector which will take care of removing objects from memory once they are not being used any longer.

What are the __ construct () and __ destruct () methods in a PHP class?

Example# __construct() is the most common magic method in PHP, because it is used to set up a class when it is initialized. The opposite of the __construct() method is the __destruct() method. This method is called when there are no more references to an object that you created or when you force its deletion.


2 Answers

In PHP all values are saved in so called zvals. Those zvals contain the actual data, type information and - this is important for your question - a reference count. Have a look at the following snippet:

$a = new B; // $a         points to zval(new B) with refcount=1
$b = $a;    // $a, $b     point to  zval(new B) with refcount=2 (+1)
$c = $b;    // $a, $b, $c point to  zval(new B) with refcount=3 (+1)
unset($a);  //     $b, $c point to  zval(new B) with refcount=2 (-1)

As soon as the refcount reaches 0 the zval is freed and the object destructor is called.

Here are some examples of the refcount reaching 0:

  • unseting a variable:

    $a = new B; // refcount=1
    unset($a);  // refcount=0 => __destruct!
    

    But:

    $a = new B; // refcount=1
    $b = $a;    // refcount=2
    unset($a);  // refcount=1 => no destruct as refcount > 0, even though unset() was called!
    
  • leaving function (or method) scope

    function a() {
        $a = new B; // refcount=1
    }               // refcount=0 => __destruct! (as $a does not exist anymore)
    
  • script execution end

    $a = new B; // refcount=1
    die();      // refcount=0 => __destruct! (on script execution end all vars are freed)
    // doesn't need to be die(), can be just normal execution end
    

These obviously are not all conditions leading to a reduction of refcount, but the ones you will most commonly meet.

Also I should mention that since PHP 5.3 circular references will be detected, too. So if object $a references object $b and $b references $a and there aren't any further references to $a or $b the refcounts of both will be 1, but they still will be freed (and __destructed). In this case though the order of destruction is undefined behavior.

like image 169
NikiC Avatar answered Sep 23 '22 05:09

NikiC


PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++. The destructor method will be called as soon as there are no other references to a particular object, or in any order during the shutdown sequence. - PHP Manual

If you want to see the process in action, you can run this code here.

<?php

class A
{
    public function __construct() { var_dump('Creating: '. get_class($this)); }
    public function __destruct() { var_dump('Removing: '. get_class($this)); }
}

class B extends A {}

$A = new A();

/*
 * When this block is called later on
 */
function create_b()
{
    $B = new B();
} // At this point the function scope ends, and since $B is not referenced anymore it's removed.


var_dump('B is next');
create_b(); // Run above block, create, then destroy be
var_dump('B is now gone');

// At this point the PHP file parser ends, $A is destroyed since it's not used anymore
like image 35
Xeoncross Avatar answered Sep 22 '22 05:09

Xeoncross