The current implementation of class Exception has a private "trace" member, which is 
used to store the backtrace. But if you throw an exception of a derived class of 
Exception, print_r() displays an empty "trace:private" member, as well as a "trace" 
(public) member that really holds the backtrace.

I deduce that the backtrace is executed/stored at the derived class level, explaining 
why a new public member is created.
Curriously, I have also noticed that "getTrace()" returns the public one, not the 
private one as expected.

This is not to report a bug, but to ask you not to fix it as it was intended ("trace" 
member as private). Indeed I use this "feature" (being able to modify the trace 
member) to hide an intermediate call:

<?
class SystemException extends Exception {
  function __construct($message, $code) {
    parent::__construct($message, $code);
    // Hide trace of handler() call.
    array_splice($this->trace, 0, 1);
    $this->file = $this->trace[0]['file'];
    $this->line = $this->trace[0]['line'];
  }

  static function handler($code, $message) {
    throw new SystemException($message, $code);
  }
}

set_error_handler(array('SystemException', 'handler'));
?>

That way, the reported error focuses on the real file and line, not on the 
uninteresting intermediate handler call.

In the current Exception class implementation, if both the "trace" member is private 
and getTrace() is final, it would be impossible to override the default behaviour. As 
a result, we would do our own exception base class, which goes against code reuse: 
need to redo all the things already done, just because the proposed class is not too 
open.

A second consequence, is that each time you use code you've got from "outside", it 
could implement its own exception base class, not using the provided Exception. If so, 
we won't be able to write generic code that guaranties to catch all exceptions (C++ 
"catch(...)" or Java "finally" not implemented in PHP5, so need to specify a class for 
catch).

The last point suggests me that PHP should guaranty that all thrown exceptions derive 
from Exception. It could be done in 2 ways:

1/ a fatal error when executing "throw new ...".
Problem: it's not easy to simulate all error conditions, so we may deliver code that 
was never tested on all its "throw" branches. As a result, the script will stop on a 
fatal error, even though it was intented to catch and handle exceptions in a clean way.

2/ even if the class is not explicitly derived from Exception, throwing it will make 
it derived from Exception.
Problem: an object of such a class will be an instance of Exception only after being 
thrown.

The 2nd is my prefered one, even if I understand it could not be so easy to implement.

One word about private and final: I don't think it's good programming to use them, 
except for security reasons. Not using them allows classes to be easily extended, in 
different directions, which is the goal of OOP.
Moreover, all members should be protected, not public, and accessed through (virtual) 
methods, which guaranties that everything can be overriden if needed.

Regards,
Stephane

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to