Page 1 of 2
_destruct : Quick question
Posted: Tue Jul 28, 2009 10:24 am
by marty pain
If header(location:<url>) is used in a script, are all the classes used prior to this properly destructed, as in the user defined _destruct functions are called if they exist?
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 10:42 am
by andyhoneycutt
To my knowledge, yes. If memory serves me correctly, the script finishes execution even after a call to header('location...'), which would imply that classes destruct. I'm curious, I'll give this a test real fast and see what happens.
Yep, testing seems to confirm this:
Code: Select all
<?php
class Test
{
private $fp;
public function __construct() {
$this->fp = fopen("/tmp/test.txt","a");
fputs($this->fp,date("Y-m-d H:i:s") . " construct.\n");
}
public function __destruct() {
if( $this->fp )
{
fputs($this->fp,date("Y-m-d H:i:s") . " destruct.\n");
fclose($this->fp);
}
}
}
$t = new Test();
sleep(3);
header("Location:http://www.google.com");
Code: Select all
2009-07-28 09:35:51 construct.
2009-07-28 09:35:54 destruct.
-Andy
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 10:52 am
by marty pain
Excellent thanks mate.
That does leave me with a problem though as one of my classes isn't destructing properly!
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 11:01 am
by andyhoneycutt
I would imagine there are circumstances that would make it destruct improperly. Perhaps things that work on the output buffer... what's your destructor look like?
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 11:18 am
by marty pain
The PHP $_SESSION is wrapped up in a class so information can be stored in a database, the destructor just calls session_write_close();
Code: Select all
function __destruct() {
session_write_close();
}
Bit worried as the same code works on our main server. The only difference is that the server uses PHP 5.2.4 and is running Ubuntu server and my machine uses PHP 5.2.9 and running Fedora 11. I have double checked everything (really everything) in php.ini and all is the same.
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 11:26 am
by andyhoneycutt
Check the documentation for
session_write_close. It looks like you need to make session call stuff before you make a header call. session stuff hits the output buffer, so this makes sense. It also looks like if everything is functioning normally, you don't typically need to make a call to session_write_close as session data should expire and commit normally unless you have two or more scripts hitting the same session at the same time.
-Andy
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 11:36 am
by marty pain
Thanks, I'll have a read tomorrow as it's the end of the day.
Any idea why there might be inconsistent behaviour between the two installs/versions?
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 11:50 am
by andyhoneycutt
I imagine the difference in behavior is that one is warning silently and the other may not be. it sounds like operationally they're the same. can you confirm if the session is closed from the mysql db on both servers, after the __destruct ?
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 12:06 pm
by marty pain
Both the server and my machine use the same database which is located on the server. I will check the status of the session in the DB tomorrow as i'm off for a well earned drink!
I just had a quick read on php.net via your link and it looks like lots of people have had the same sort of problem as me. I added a die(); on the line after the header, as recommended, and it's fine now, as it officially ends the script, which in turn calls the destructor.
Thanks for the help Andy! Really appreciate it mate!
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 12:29 pm
by andyhoneycutt
Any time! Have a drink for me, I haven't earned one yet today

Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 1:38 pm
by andyhoneycutt
McInfo wrote:I think your test script is a little misleading, andyhoneycutt, because the call to header() appears on the last line of the script. It should not be assumed that header() triggers the destructor.
Oh, my apologies! I didn't mean to imply that header
was triggering the destructor, rather that the script finishing execution causes the destructor to trigger.
McInfo wrote:The destructor is not called:
Code: Select all
$c = new C;
sleep(2);
header('Location: ./other.php');
This is essentially the same logic I posted, which does in fact call the descrutor at the end of script execution. I'm wondering why it wouldn't on your setup but does on mine.
-Andy
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 2:57 pm
by pickle
You should always call exit() after a header relocation. That should destruct everything.
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 3:34 pm
by McInfo
pickle wrote:You should always call exit() after a header relocation. That should destruct everything.
There are a few exceptions. You should
usually call exit() after header relocation.
Edit: This post was recovered from search engine cache.
Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 3:46 pm
by andyhoneycutt
McInfo wrote:I found a clue.
PHP Manual wrote:Note: Destructors called during the script shutdown have HTTP headers already sent. The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache).
I was using a relative path for file_put_contents(). When the current working directory changed, the file was saved to a different location. After changing to an absolute path, the file was saved in the same location every time. That indicates that the destructor was called every time.
Very cool. Thanks for the info

Re: _destruct : Quick question
Posted: Tue Jul 28, 2009 3:51 pm
by McInfo
marty pain wrote:user defined _destruct functions
This seems unlikely to be the problem since you wrote it correctly later, but make sure you are using two underscores.
Edit: This post was recovered from search engine cache.