2008
05.23

Once again a post aimed at the PHP community, not so much of a rant but more of something I’ve seen done horribly wrong in a lot of PHP code recently, first let me take a few examples from a couple of well known PHP frameworks and libraries:

symfony, file: lib/database/sfMySQLDatabase.class.php

$error = 'Failed to create a MySQLDatabase connection';
throw new sfDatabaseException($error);

propel, file: runtime/classes/propel/util/BasePeer.php

throw new PropelException("Expecting to delete 1 record, but criteria match multiple.");

doctrine, file: lib/Doctrine/Connection.php

throw new Doctrine_Connection_Exception('First argument should be an instance of
PDO or implement Doctrine_Adapter_Interface');

I could go on and on and list a couple of hundred of these from each of most poplar PHP libraries, and they all make the same assumption: An exception is a fatal error. And by making this assumption and using one monolithic “DatabaseException”-class, it becomes impossible to handle the exceptions in any other manner then as a fatal errors.

For example the first snippet, coming from the symfony framework is thrown when you can’t connect to a database. Since every other error that can happen to any database connection done in symfony also throws a “sfDatabaseException” how is the user of the library supposed try a backup database or supply a custom “database is down”-error page ? By regex:ing the message of the thrown exception?

Exceptions are not, and I repeat not, a fatal error mechanism (they can be, sure – but it’s not their only or primary use). Taken the above symfony code again, it should look something like this:

throw new DatabaseConnectionFailedException('MySQL');

Or something along those lines, making it possible to somehow distinguish between different type of exceptions allows us to do something like this (again assuming the symfony code):

try {
         // Try to connect to a database

} catch (DatabaseConnectionFailedException $e)  {
         // Try backup database

} catch (DatabaseException $e) {
         // Generic database error
}

So, to sum it up:

Exceptions, you’re doing it wrong!