Exception Tree design (Help and Comments requested)

I’ve got my framework working well enough when things go right. Time to make it work well enough when things don’t go right. So the next couple weeks I’m going to devote to getting a strong exception structure put in place. Here’s what I have.

All of these live within my framework namespace.

Core Exceptions
These exceptions are at the root of the hierarchy. Some aren’t throwable, others should only be thrown rarely.

abstract PNL\Exception extends \Exception
The root exception class attaches the methods that are globally available in this schema. When an error occurs it is logged to the database if the database connection is available, logged to the file system when the error occurs before database services can be obtained. The error then reports back to the user - either a terse “something went wrong” message for production to a full on chatty Kathy soup and sandwich info dump for development. The exception class knows how to call upon a html or javascript handler to echo the response back - the javascript side of the framework will know how to communicate this information upward without having to write code.

Basically anything the exceptions may be called upon to do is at this level. This exception is itself not meant to be thrown - it’s abstracted for that reason.

[INDENT]FatalException extends Exception
Fatal exceptions are not to be caught by userland code. The whole point of this group is to allow them to escape to the framework itself for mitigation. If the developer has an exception they expect to catch then it shouldn’t be fatal.

Fatal Exception itself will bring the system to a halt. The framework assumes that it cannot proceed - when it catches a fatal it gracefully dies on the spot - if it catches another fatal while attempting to gracefully die then it panic dies in a manner not unlike Kernel Panic or BSOD.

[INDENT]ErrorException extends FatalException
This is thrown for errors other than E_USER_NOTICE, E_USER_WARNING and E_USER_DEPRECATED. Those three will be logged but not converted in production. In development they too will raise an ErrorException bringing the system to a halt.

So yes, this means, occasionally, the framework uses the older trigger_error mechanism for situations that are tolerable but inadvisable (Attempts to access non-accessible members of an object for example, trigger a notice and null is returned).

InternalFileNotFoundException extends FatalException
Raised when a file that should exist, such as a template or class definition, doesn’t exist.
[/INDENT]

GenericException extends Exception
All “non-fatal” exceptions extend off Generic exception. Use of generic exception is discouraged. The framework catches these at the event mitigation level and after resolution proceeds to the next event if possible.
[/INDENT]

Protocol Exceptions
These exceptions arise out of the HTTP 1.01 protocol. The framework provides default response pages for all of these but users can override them in their project files as needed. All of them can become raised as a result of userland actions. The presence of these codes is a consequence of PHP directly negotiating requests to the directory.

Note: When the other errors listed here “escape” to userland the HTTP header will be 500

abstract HTTPException extends GenericException
This root exceptions contains the methods the family must use. For the most part the children of this class are only labels.

[INDENT]
MovedPermanentlyException extends HTTPException
Code 301. If you change a page’s name in the CMS layer the old name is remembered for awhile so that this redirect can be sent. Users are discouraged from reusing the names of moved resources for a period of time to prevent link confusion.

NotModifiedException extends HTTPException
Code 304. This will be reserved for implementation later on. By it’s nature it deals with caching interfacing.

NotFoundException extends HTTPException
Code 404. When the resource doesn’t exist and there exits no alternative

NotAuthorizedException extends HTTPException
Code 403. This gets used when users fail log ins and the like.

BadRequestException extends HTTPException
Code 402. This is thrown for illegal or invalid $_GETs and $_POSTs. In development a programmer may trigger these, in production a hacker attempting penetration will.

ConflictException extends HTTPException
Code 409. Thrown when the system is using resource locking in response to the user attempting to open for editing a resource another user has open for editing.

GoneException extends HTTPException
Code 410. When you delete a page file in the framework CMS system it will initially be marked with a deleted flag and an this exception rather than 404 is raised. This persists for 90 days by default.

ServiceUnavailableException extends HTTPException
Code 503. Thrown when the developer or administrator has set the site open flag to false. It is possible to log in as a developer or admin. Again, this exception is rather specialized.[/INDENT]

Database Exceptions
These come out of the database.

abstract DatabaseException extends GenericException
Contains root methods used by the various database exceptions.

[INDENT]
ConnectivityException extends DatabaseException
Thrown when database connection cannot be completed.

ValidationException extends DatabaseException
Proposed input to a field is incorrect. This typically should be caught and the user alerted to what they did wrong.

TimeOutException extends DatabaseException
Query is valid, but encompasses a range too large to fulfill. Typically found in searches, and the user will need to contract their search parameters.

QuerySyntaxException extends DatabaseException
Thrown when the query fails to run due to syntax[/INDENT]

And that’s what I have now, but it’s enough to show the basic structure and how it should grow. Thoughts or comments?

As it happens my current reading is Java Exceptions, and I came across the idea of an IllegalArgumentException (in java.lang), something I would not have thought of creating or even needing in PHP.

Might Exceptions specific to the workings of classes have a place in your hierarchy?

FYI


public static double sqrt( double x){

if( x < 0 ) 
  throw new IllegalArgumentException(x + ' is less than zero.');

// calc sqrt of x

}

Given the loosely typed nature of PHP vs Java, perhaps this kind of error handling is even more important?

It never dawned on me to do things this way, and I’d thought I’d air it in your thread - hope you don’t mind.

ps found these subclasses of the above:

IllegalCharsetNameException, IllegalFormatException, IllegalSelectorException, IllegalThreadStateException, InvalidKeyException, InvalidOpenTypeException, InvalidParameterException, KeyAlreadyExistsException, NumberFormatException, PatternSyntaxException, UnresolvedAddressException, UnsupportedAddressTypeException, UnsupportedCharsetException

PHP itself throws catchable Fatal Error or somesuch when argument types don’t match so these can be checked for by type hinting. That only goes so far in PHP 5.3 since you can’t test for strings. For the moment tests or arguments are done with assertions since, in production, they should not fail (if that isn’t true assertions aren’t used since they are turned off in production).