basically when php shutsdown at some stage stuff like file manipulation,
db access will have been torn down - the implicit object destruction (and
therefore the call to __destruct() happens to late in the shutdown process
to be of any use ... there is a big chicken and egg problem there (search the
archives of the php-internal mailing list should reveal lots of discussion
surround this topic)
further comments below ...
John Wells wrote:
I hope I can explain my problem/questions clearly. Thanks in advance:
------------
Scenario:
I'm working on a Log class that my app will use to write
debug/error/etc messages to a file. I've created it so that as the
application logs messages, these messages are queued within a property
of the Log class, and only written to the file when the Log object is
being destroyed.
I wanted to place all of the file writing to within __destruct() to
avoid holding a connection to the log file throughout the life of the
app's state.
------------
Problem:
Everything works fine, UNLESS I move the fopen('log-file-name') call
to within the __destruct() method. If I open a handle to the log file
within the __construct() method, or any other class method, it works
fine. But I receive a permissions error if it's called within
__destruct().
Error reads: "Warning: fopen(20060331.txt) [function.fopen]: failed to
open stream: Permission denied in ......."
------------
Caveat:
I have found that if I explicitly destroy an instance of Log with
unset(), then fopen() will work even when it is within the
__destruct() method. However I don't like that solution...and
besides, I'm planning on creating an instance of the Log class from
within the __construct() of my Controller class, and trying to
explicitly destroy Log with an implicit __destruct() of my Controller
doesn't work either. :P
that's probably due to references still existing (according to the engine)
to you Log object.
------------
Question(s):
1. Could anyone explain a bit more as to why fopen() won't work within
an implicit call to __destruct()? What permissions has my app lost at
this point?
it's seems rather odd that the error would return a permission problem.
I don't get that at all.
2. Am I at least correct in my intention to limit the duration that
the handle to the log file is open?
it's a good idea yes - any system will have some kind of max as to the
number of open files that are allowed/capable.
3. Is there workaround to this little conundrum that anyone can think of?
explicit destruction. may try working with register_shutdown_function()
- the ctor of your log object could register a 'flsuh' method to be run at
shutdown (which may well be at an early enough stage that opening/writing
files is still possible)
personally I avoid __destruct() - it gives me headaches and never seems
capable of doing what I think it should be able to!
------------
Code:
Here's a simplified version of the code (it's complete, feel free to
copy-and-paste-and-play). I've commented the fopen code block in
question.
[code]
// Create an instance of Log
$log = new Log();
// Attempt to log a message
Log::debug("Here is a debug message.");
class Log
{
protected static $handle;
protected static $location;
protected static $message;
public function __construct()
{
self::$location = date("Ymd").".txt";
/* Begin fopen() */
/* When placed here, it works */
if (!self::$handle = fopen(self::$location,"a"))
{
echo "Error. Please check permissions.";
die;
}
/* End fopen() */
}
public static function debug($message)
{
$timestamp = date("Y-m-d H:i:s T");
self::$message .= $timestamp."\tdebug\t".$message."\n";
}
public function __destruct()
{
if(self::$message)
{
/* Begin fopen() */
/* If it's here, it won't work!
if (!self::$handle = fopen(self::$location,"a"))
{
echo "There was an error attempting to
open the log file. Please
check permissions.";
die;
}
/* End fopen() */
if (fwrite(self::$handle, self::$message) ===
FALSE)
{
echo "Cannot write to file
({$this->location})";
exit;
the 'die' and 'exit' in the code directly above is probably a really bad idea!
and given that the code is currently living in a dtor rather unnecessary?
}
@fclose(self::$handle);
}
}
}
[/code]
-John W
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php