Friday, November 26, 2010

Basic exception usage in php

Theory

If you have not already, check the official php documentation on exceptions at http://php.net/manual/en/language.exceptions.php. Besides some php specifics, here you can find basic example how to use try catch blocks and how to work with exceptions.

Example goes like this:
function inverse($x) {
 if (!$x) {
  throw new Exception('Division by zero.');
 }
 else return 1/$x;
}

try {
 echo inverse(5) . "\n";
 echo inverse(0) . "\n";
} catch (Exception $e) {
 echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';

Through this example you can see that if a process finds itself in a problematic situation, it can throw an exception. This exception can be caught, and that way we will prevent system to run into some php fatal error.

This are the theoretical basics, however, the real question is how and where to use exception handling in your  applications and scripts.



Front Controller
Front Controller is engine which runs your web application. If you are using a Zend Framework, then you are  probably using their MVC too. This MVC has in itself a front controller logic already built. On the other hand, if you have some of your engine that runs all requests through the index.php, then you probably have one class which carries the logic for including and executing different pages, or classes - that is front controller.
Theoretically, front controller is the only place where you should try to catch exceptions and probably log some info about it. In practice, you will catch them and even elsewhere, but I'll describe that issue some other time. This is quite enough for the beginning.
class Application
{
 public function init()
 {
  $page    =    $_GET['page'];
  try
  {
   require_once $page.'.php';
  }
  catch (Exception $e)
  {
   error_log( $e->getTraceAsString(), 3, 'error.log');             
   require_once 'error_page.php';              
  }
 }  
}

This is an example of a very simple application which will, depending on the passed GET parameter try to include (and execute) appropriate php script file.
It is important to note that this example shows that inside those included php scriptis, you can safely call any method that can throw the exception. You can even throw exceptions by yourself if you miss something for finishing requested process. When you have such a "rounded" application, exception will be logged and the user will be presented to an error page.
This is actually a minimum, bottom line, that your engine must comply.



Other classes
A simpler case is when you are developing "regular" classes, such as a daos for getting stored data. While building such classes, you do not have to think about what will hapen latter in other classes and processes if for example databes connection is broken, or user tries to hack the url parameters, or anything else goes wrong. You have to concentrate only on your "local" world, inside your calling method, and make it sure that the method executed well. In other words, either method will do all what is required from it, or otherwise if something is wrong, it will throw the appropriate exception.

class UserDao
{
 public $users    =    array( 1=>'Anny', 2=>'Sandra', 3=>'Monica');

 public function getUser( $userId)
 {
  if (!isset($this->users[$userId]))
   throw new Exception('User ['.$userId.'] not found in local array');

  return $this->users[$userId];
 }
}

This is a classic example where many web developers will return null and maybe try to define an error message that goes to the enduser. This is wrong because if you return null you are risking that an error passes  unnoticed. In that case your user can get the message "Hello Mrs null", and that is the better case. If you are working with the objects, you risk the fatal error after calling a method or property on the object which is null.

If, as in this example, you throw the exception, you can be sure that it will not go unnoticed. In addition, you have the opportunity to describe what happened in exception message, and help your self in latter bug tracing  sessions.
I would like to mention that in such cases it is better to throw some custom UserNotFoundExecption, but I'll explain the use of exception subclassing in another article.

Friday, November 19, 2010

Why exception handling is important in php?

    I work as a professional programmer for 10 years and in those 10 years I met a bunch of different developers. In plenty of them, especially in web / php developers, I could notice a lack of understanding of the concept of throwing and catching exceptions and what does it serves for. Of course, the first I noticed it at myself. In this blog I would like to point out a number of useful things that proper use of the exception can make, and which were slipping from my hands for a few years too.

    Exceptions are providing a standardized way to control problematic processes and they are reducing the possibility of fatal errors in the application. If process throws exception, you are forced to handle situation in your application, and it will automatically reduce the possibility that some problem sleeps out whit out being processed. When you're working with exceptions, you are handling problems at low level, so it will not make you problems with your higher layers, e.g displaying error messages to user.

    Work with exceptions make it easier to fix bugs when they happen. Errors in applications will always happen, especially in the real world of short deadlines and often requirement specification changes. However, when something goes wrong in your application, the question is when will you and will you even notice at all that something went wrong? And, also, how quickly you will know exactly what happened and what needs to be corrected? If you are working with the exceptions, this can be quite clear and painless issue that you will quickly and efficiently solve.

    PHP only since version 5 delivers the work with conventional try / catch system and it's quite a big problem for those developers who have not dealt with eg Java or C# too. In future posts I'll try to explain few simple general rules to follow that will help you to make the exceptions are not the problematic to you, but a tool which will increase your speed and quality.