When Will _Destruct Not Be Called in PHP

Are there any instances when the destructor in PHP is NOT called?

  • According to the manual, destructors are executed even if the script gets terminated using die() or exit():

    The destructor will be called even if script execution is stopped using exit(). Calling exit() in a destructor will prevent the remaining shutdown routines from executing.

  • According to this SO question, the destructor does not get executed when PHP's execution time limit is reached (Confirmed on Apache 2, PHP 5.2 on Windows 7).

  • The destructor also does not get executed when the script terminates because the memory limit was reached. (Just tested)

  • The destructor does get executed on fatal errors (Just tested) Update: The OP can't confirm this - there seem to be fatal errors where things are different

  • It does not get executed on parse errors (because the whole script won't be interpreted)

  • The destructor will certainly not be executed if the server process crashes or some other exception out of PHP's control occurs.

All in all, it looks pretty reliable.

The downside of doing things other than cleanup in the destructor, though, is that your options there are somewhat limited. You can't throw exceptions any more (except if you catch them again inside the destructor), you can't output any error messages, you can't really rely on the presence of other objects (like the database interface) any more ..... I don't have deep experience in working with destructors but I'm not sure whether what you're planning to do is a feasible idea.

Can I trust PHP __destruct() method to be called?

The destructor will be called when the all references are freed, or when the script terminates. I assume this means when the script terminates properly. I would say that critical exceptions would not guarantee the destructor to be called.

The PHP documentation is a little bit thin, but it does say that Exceptions in the destructor will cause issues.

Does __destruct run by itslef or do I need to use unset() or register_shutdown_function() in order for it to work

No, the unset() function is not the only way to call __destruct(). According to the documentation, “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”.

To illustrate this, consider the following methods when __destruct() will be called automatically:

1) It is called instantly when the class instance is not assigned to any variable:

<?php
new TheClass(); #-> this line calls __destruct()

/* More PHP Code */
?>

2) It is called when script execution is stopped:

<?php
$obj = new TheClass();
exit; #-> this line calls __destruct()

/* More PHP Code */
?>

3) It is called when unset() destroys the reference of the class:

<?php
$obj = new TheClass();
unset($obj); #-> this line calls __destruct()

/* More PHP Code */
?>

4) It is called when the value of variable is reassigned:

<?php
$obj = new TheClass();
$obj = 'any value'; #-> this line calls __destruct()

/* More PHP Code */
?>

5) It is called when the script completes its execution:

<?php
$obj = new TheClass();

/* More PHP Code */

#-> this line calls __destruct()
?>

6) It is called when exiting variable scope:

<?php
call_user_func(function() {
$obj = new TheClass();

/* More PHP Code */

return true; #-> this line calls __destruct()
});

/* More PHP Code */
?>

When (at which moment) is __destruct called?

Yes, you can assume that.

__destruct is always called at the moment where the last reference to the object disappears: when you can't access that object anymore in any way from the outside.

If there exist circular references, you need to wait until it circular garbage collector comes in, where it isn't defined at what point that happens.

If you have stored the object somewhere else too, you need to first remove it from there before the destructor is called.

For further information: Internal objects don't always destruct their resources upon __destruct (as the user might call it directly), but only when the object really is destroyed. (technical measure to prevent segfaults)

Also during shutdown, first variables and arrays are removed in the reverse order they were defined and where the last reference to an object disappears the object is destroyed. Then circular garbage collector comes in and removes the other objects and calls __destruct there.

The only thing which is undefined here, is the order in which the circular garbage collector removes objects and calls their __destruct function.



Related Topics



Leave a reply



Submit