If we were to argue about what are the most useful things that have come into modern PHP, Exceptions would be one of the first things that would come to mind, and it's still one of the features that most amateur developers tend to leave aside. However, adequately used, Exceptions give total control on what happens within your application, and most specifically when things go wrong which is when it is most important to try and keep things in check. Out of the box, Exceptions provide limited but useful information, mainly a message, an error code and some background information on what was being run at the time... but with some skillful plumbing we can get a lot more juice our of them. Enter the Custom Exceptions!
In fact, Exceptions are meant to be simple in their simplest form. This way they can provide a clean and reliable set of tools with which we can construct some pretty mean guards to keep our applications in check. Only we know what's going to go on in our application, and only we know what it's going to take to keep everything in shape! Most of the time, we know when things can go wrong and how they can go wrong and hence it is easy to protect and correct, but it's when things go unexpectedly wrong that custom exceptions come in very useful as they can give very precise information on exactly where the issue is, and its nature. To this end, it is important that each possible source of conflict be uniquely labeled and identified in a way that will take us directly to the source of the problem. An excellent way to achieve this is to relate each class to a unique exception class, and give every single possible problem a unique ID. Take a simple example:
try {
Database::connect();
$user = new User($id);
$valid = $user->login($password);
}
catch (DatabaseException $e) {
$errorMsg = 'There was a database problem';
}
catch (UserException $e) {
if ($e->getCode()==1) $errorMsg = 'The user doesn't exist';
elseif ($e->getCode()==2) $errorMsg = 'User and password don't match';
else $errorMsg = 'An error has occurred, our devlopment team has been notified';
}
In this case, the error codes are very simple and provide little information, but they can be tailored to be a little more detailed, even if they can only be numerical strings. A quick example of this would be to imagine an application being run in different environments, and in which different exceptions can be assigned a "criticality factor" which would decide how bad he exception is and wether the application can continue. In this case we can divide the numerical error into three parts which would provide necessary information: the first three would indicate the environment, the next three would specify how bad the error is and the last three the ID of the actual exception being thrown. Therefore an exception with code 003001028 would tell us that Exception 28 has been thrown in environment 3 with a '1' criticality factor. Hence we can decide if we want to continue executing the script or jump to the 'site down' page, and which server's logs we have to fetch to see what was going on at the time.


