Re: __Destruct() functionality

php.internals

Florian Schaper

22 years ago
Marcus Boerger wrote:
> Hello Gareth, > > __destruct will get executed during request shutdown after the > communication has been shutdown. The only way to be able to write > from within __destruct is to deinitialize it at the end of the > script and therefore before the request is being finished. To > do so you can use 'unset($object);' >
But then again why call destruct on the objects after the external modules have been shut down? This heavily confuses people and I see no apparent reason to do so (then again I'm not deep into the PHP internal structure)? I find it highly attractive to be able to save a "session"-object via my destructor / close DB connections - you name it. zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); before php_call_shutdown_functions(); etc. Can somebody enlighten me? ./regards Florian

Gareth Ardron

22 years ago
On Mon, 2004-06-28 at 12:25, Florian Schaper wrote:
> > __destruct will get executed during request shutdown after the > > communication has been shutdown. The only way to be able to write > > from within __destruct is to deinitialize it at the end of the > > script and therefore before the request is being finished. To > > do so you can use 'unset($object);'
> But then again why call destruct on the objects after the external > modules have been shut down? This heavily confuses people and I > see no apparent reason to do so (then again I'm not deep into the PHP > internal structure)? I find it highly attractive to be able to save a > "session"-object via my destructor / close DB connections - you name > it. > > zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); > before php_call_shutdown_functions(); etc.
This is where I was heading as well in the original mail :) There's a huge amount of scope within __destruct() to be able to pull off a load of tricks really nice and cleanly - even if that's just closing db connectections or extra logging, it's still really nice. while I'm happy to unset($object), this is rather an ugly way round what could be quite an elegant feature. What I found really confusing though, was the documentation on this subject. The docs state that __destruct() is called with no parameters when the last reference to the object is removed from memory. It's not immediatly apparent that this happens during shutdown; I'd have guessed at just before. This meant I spent half an hour changing things round to see if I could work out just how it was working. Really annoying thing being that if a class has a private variable which is itself an object of another class, and you do something like this inside the __destruct() function: $this->logger->logEvent("leaving class"); then not only doesn't it work, but you don't get any errors either. However, this would give you an error: $this->logEvent("leaving class"); At the very least, could somebody poke the docs a bit to reflect this a bit better? (though I'd prefer the way destruct is called to be changed ;-) )

Florian Schaper

22 years ago
Gareth Ardron wrote:
> On Mon, 2004-06-28 at 12:25, Florian Schaper wrote: >
[...]
>( though I'd prefer the way destruct is called to be > changed ;-) )
For what it's worth, i'd second that. ./regards Florian

Marcus Börger

22 years ago
Hello Florian, there is no problem in calling resource destructors/terminators in your destructors. You simply cannot output text to your pages from them. If this is not true then we need to fix it. For example if an object of yours holds a database connection and your destructor executes some SQL code this must work. Open a bug report if necessary. regards marcus Monday, June 28, 2004, 1:25:15 PM, you wrote:
> Marcus Boerger wrote: >> Hello Gareth, >> >> __destruct will get executed during request shutdown after the >> communication has been shutdown. The only way to be able to write >> from within __destruct is to deinitialize it at the end of the >> script and therefore before the request is being finished. To >> do so you can use 'unset($object);' >>
> But then again why call destruct on the objects after the external > modules > have been shut down? This heavily confuses people and I see no apparent > reason > to do so (then again I'm not deep into the PHP internal structure)? > I find it highly attractive to be able to save a "session"-object via my > destructor / close DB connections - you name it.
> zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); > before php_call_shutdown_functions(); etc.
> Can somebody enlighten me?
> ./regards
> Florian
-- Best regards, Marcus mailto:helly@php.net

Florian Schaper

22 years ago
Marcus Boerger wrote:
> Hello Florian, > > there is no problem in calling resource destructors/terminators in > your destructors. You simply cannot output text to your pages from > them. If this is not true then we need to fix it. For example if an > object of yours holds a database connection and your destructor > executes some SQL code this must work. Open a bug report if necessary. >
Well you can output text in destructors. All other functions are also available but _might_ not behave the way we would expect them to. I was wrong regarding the mysql extension - (really bad guesswork on my part). However if I'm not wrong this time (again I might, since I have no dev. environment with me right now to check back with the sources) the extensions PHP_RSHUTDOWN_FUNCTION is called _before_ object destructors are called. That seems now to be the problem already stated in "documentation" bug ( #27555 ). Developers might well clean up their stuff at that point in the extension (like write the session to disk in the session ext.) expecting the session to be "over" what leads to confusing results for people (extension and php developers alike) when it actually isn't. ./regards Florian

Gareth Ardron

22 years ago
On Tue, 2004-06-29 at 18:55, Marcus Boerger wrote:
> Hello Florian, > > there is no problem in calling resource destructors/terminators in your > destructors. You simply cannot output text to your pages from them. If > this is not true then we need to fix it. For example if an object of > yours holds a database connection and your destructor executes some > SQL code this must work. Open a bug report if necessary.
Does the examples I gave you before not count ? To reiterate: <?php // db in this sense is an already initialised database class // basic wrappers around the mysql functions in my case. class logger extends db { function logEvent($msg){ // somecode here which uses the parent db class // to write the msg to a database } } class someOtherClass { public $log; function __destruct(){ $log->logEvent("leaving someOtherClass"); } } $log = new logger; $soc = new someOtherClass; $soc->log = $log; ?> in this case, the __destruct() function within someOtherClass does absolutly bugger all.

Adam Maccabee Trachtenberg

22 years ago
On Wed, 30 Jun 2004, Gareth Ardron wrote:
> Does the examples I gave you before not count ?
Yes. It does not count.
> in this case, the __destruct() function within someOtherClass does > absolutly bugger all.
You can't reference one object from another's destructor. PHP makes no promises about the order it'll destroy your objects during shutdown. If you require objects to be destroyed in a particular sequence, then you need to unset() them manually. This issue has been discussed previously. Check the archives for more information about why this is and why "fixing" it is difficult / impossible. -adam
-- adam@trachtenberg.com author of o'reilly's php cookbook avoid the holiday rush, buy your copy today!