Exception Handling In PHP5 – Good Cop, Bad Cop

Exception handling. The "I'm so good, I don't produce errors"-mentality can't even save you from them. It's bound to happen -- either your code fails, or external libraries you've grown to accept produce faults outside of your control.

You need'm handled, it's that simple.

And PHP offers you a couple of methods to "handle" errors, or warnings, generated by your PHP code. From basic Error Suppresion, to proper Exception Handling.

Take the following little example.

$db = mysql_connect($hostname, $username, $password);

The code above is one of the most common function calls in any website. Establish your database connection (in this case, to a MySQL server). While simple in theory, a lot can go wrong; MySQL server not running on that particular host, incorrect username/password, ... You just don't know how it'll be handled.

You could expand it, to do the following.

$db = mysql_connect($hostname, $username, $password) or die (mysql_error());

Should anything go wrong, you'll immediately show the corresponding MySQL error message. While this may be good for you -- now you have the necessary information to debug -- your visitor, who couldn't even spell MySQL if the life of his newborn puppy depended on it, would just be annoyed.

Thus, we suppress the message. We don't show the error message, we hide it. PHP's Error Suppression is done using the @-sign, in front of your function call.

$db = @mysql_connect($hostname, $username, $password);

We may have hidden our error messages, we still haven't handled them. We just prevented them from showing up.So how do we know the connection was established correctly? By checking the return type!

$db = @mysql_connect($hostname, $username, $password);
 
if (!$db) {
	echo "Connection failed.";
}

This will allow us to display a proper (and more importantly; a self-chosen and self-handled) error message to our visitor, instead of a message defined by MySQL which would just be jibberish to most.

When you want to disable your error message entirely, you can use the following code on top of your page. It will override any setting defined in the php.ini, all code behind this function call will have its errors/warnings/notices removed.

error_reporting(0);  // Disable all error reporting

You should note that, despite not showing any notice, warning or error message, script execution will stop when it reaches a fatal error message -- and you won't be notified of the error. The page will simply come to a halt, without a clue as to what happened, and where.

But there are occasions when there's more need of handling an "Exception", than of handling an Error. That's why there is some advanced Exception Handling available to you in PHP5.

Let's say you have the following base class "Person", that has a method "Talk" to say a line of text "Hello World!".

class Person {
	function Talk ($message) {
		echo $message;
	}
}
 
$john_doe = new Person();
$john_doe->Talk("Hello World!");

If the $message should be empty -- nothing would be shown. Thus, we need to handle the "Exception" of an empty string.

class Person {
	function Talk ($message) {
		if (!is_string($message) || strlen($message) == 0) {
			throw new Exception("People can't say empty sentences.");
		}
 
		echo $message;
	}
}
 
$john_doe = new Person();
try {
	// Attempt to say an empty sentence
	$john_doe->Talk("");
} catch (Exception $e) {
	// If the above fails, handle the exception
	echo $e->getMessage();
}

Notice how the method Talk() and its execution changed. There's now a check in place, to see if the parameter is actually a string, and if it's empty or not. If either of these checks fail, a new Exception will be thrown.

By placing the call of the Talk() method in a Try-Catch bracket, we can completely handle whatever exception message is thrown inside the method. If the Talk() does not go as planned, we can display the Exception message defined within the class.

This can be implemented further, by extending the base class Exception, and writing your own version of it -- to do exactly what you want. Take a look at the code below.

// Extend the class "Exception" with our own Exception-class
class PersonTalkException extends Exception {
    function __construct($message) {
		LoggingClass::logEvent($message);
 
		MailerClass::mailAdministrator($message);
    }
 
    public function showStacktrace() {
    	// Show a stacktrace of this error
    	echo parent::getTrace();	// Method defined in the "Exception" base class
    }
 
}	
 
// Our base class "Person"
class Person {
	function Talk ($message) {
		if (!is_string($message) || strlen($message) == 0) {
			throw new PersonTalkException("People can't say empty sentences.");
		}
 
		echo $message;
	}
}
 
// Our script execution
$john_doe = new Person();
try {
	// Attempt to talk an empty sentence
	$john_doe->Talk("");
} catch (PersonTalkException $e) {
	// If the above fails, handle the exception within the PersonTalkException class
	// And then display the error message, defined within the Person class
	echo $e->getMessage();
	// And if requested, show a complete stacktrace of this message
	$e->showStacktrace();
} catch (Exception $e) {
	// If it's not an Exception of type PersonTalkException, display the generic one
	echo $e->getMessage();
}

This will create a new class "PersonTalkException" that extends the base functionality of "Exception". It allows any exception that is thrown into this class, to be handled for this specific occasion. We can log the message, or mail it -- depending on the situation.

The Try-Catch block has also expanded. At first, we see if we can catch an Exception with the type "PersonTalkException". If the type matches, we display some specific items defined within this class.

If it's not of the type "PersonTalkException", just display the generic Exception message, without extras.

The Exception Handling should allow you to create more robust PHP applications, that won't throw quite as many error messages. Mastering Exceptions also allows you to create simpler looking, more organized applications. No more nesting of if's until infinity, but simply throw an Exception, and continue on with your code.

class Person {
	function Talk ($message) {
		if (!is_string($message)) {
			throw new PersonTalkException("That's not a string!");
		}
 
		if (strlen($message) == 0) {
			throw new PersonTalkException("It's a string, but it's empty!");
		}
 
		echo $message;
	}
}

Keep your code clean, and make it easier for you to maintain endlessly large projects.

You can also define your own Error Handler Function (instead of just Exceptions, as shown above), by using the set_error_handler() function. This allows you to "catch" any error that might occur -- including the ones not handled by Exceptions.

Hi! This is a blog where I write down solutions to some of the problems I've faced when working as a sysadmin/dev. I hope you find the information shown here useful to you. Please use the comments on this blog to give feedback about the content!. I'm @mattiasgeniar on Twitter.

Tagged with: , , , ,
Posted in php
5 comments on “Exception Handling In PHP5 – Good Cop, Bad Cop
  1. Jeff says:

    mysql over mysqli or PDO? really? /And/ the error suppression operator? good lord.

  2. Matti says:

    Actually, Error suppression (@) has a proper use, in certain situations. Ignore certain warnings, when they can’t be controlled through the ini_set-operator. It shouldn’t be used to “remove error messages”, as that’s where the Exception handling comes in.

    And mysql-connections are used in 90%+ of the PHP websites, so I’d reckon it’s a fair example to use here.

  3. Loïc Hoguin says:

    Quick tip, I’ll let you think about it. Use a custom error handler to throw an ErrorException, and you can catch PHP errors like you would catch exceptions.

  4. hadoota says:

    this is wonderful tutorial .. i read it 3 times and get a fantastic results and sure i put a
    copy of this lesson on my site here

  5. So much tnx, i didn’t knew that @ hides the error messages. sorry by the spanglish i’m from latin america.

4 Pings/Trackbacks for "Exception Handling In PHP5 – Good Cop, Bad Cop"
  1. [...] Exception Handling In PHP5 – Good Cop, Bad Cop ~ Mattias Geniar Catching and handling errors in PHP5. (tags: php php5 programming error errorhandling) [...]

  2. Exception Handling In PHP5- php tutorial…

    What is Exception Handling?
    An exception (or exception handler) is a programming language construct that lets web developers have a better control over error handling. Most web sites development services have the option to extend this with their own cu…

  3. [...] last weeks explanation on how to handle errors & exceptions in PHP5, it’s time to advance in this area. Using PHP’s PDO (PHP Data Object), you can create [...]

  4. [...] am starting to feel exceptions are useless, and maybe even evil. That last link, for example is a perfect example of code that looks good on the surface but in my [...]

Leave a Reply

Your email address will not be published. Required fields are marked *

*

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>