Welcome to my site

Post statistics

PHP exception handling

Arguably one of the best things to come out of PHP5 was its improved OO support. With OO comes easier separation of presentation, data, and business logic layers which leads to reusable code and better code management, amongst a host of others.

Example of an error

Exception handling appears daunting a first, but once you understand the concept it is very easy to use, and incredibly powerful. Let’s start off with an example of an error to demonstrate what we mean.

<?PHP
$a = Array("foo", "bar", "foobar");
$b = 10;
$c = $a + $b;
echo($c);

That small PHP block when parsed will produce the following error: Fatal error: Unsupported operand types in simple_php_error.php on line 5.

We get that error because we are trying to add an array data type to an integer data type. Since we can not possibly add them together, an error occurs. Although these are not the type of errors we will be dealing with via exception handling, they do give you an idea of why we would want to hide errors.

Why use exception handlers?

First and foremost it makes your applications far more professional. Users visiting your site do not want to be bombarded with error messages here, there and everywhere. Not only do they not want to see them, but inexperienced users could get confused—did they create the error themselves? Did they somehow brake the site? Oh dear, let’s quickly run away from this site!

By using exception handling we can catch these errors and deal with them how we choose. We could even hide them completely and just log them for you to observe and correct at a later date.

So who uses exception handling? Well, me for one. Not only me, but nearly ever other major PHP developer will rely upon them at some time in a project. So should you.

Alternatives to exception handling

There are several alternatives to exception handling, but each have their downfalls.

  • error_reporting()
  • The @ operator

error_reporting() is a function that tells the PHP engine what errors to display. Whilst in development stages, it is a good idea to have it set as E_ALL, and whilst in live stage, hide all the errors—after all, we don’t want them possibly knowing our database or file structure—that could become a security risk. The downfall of error_reporting() is that you can only show and hide the errors, you cannot handle them.

The @ operator suppresses any errors that may occur. You add it before a statement which could possibly cause an error, for instance:

<?PHP
@fopen('location/of/your/script.php', 'r+');

The downfalls of this operator is that it is greedy. By including the file via this method you will also be suppressing any errors within that file also. Whilst in development stages this is a very bad idea. If you have done this or rely upon it, give yourself a smack on the hand. The only realistic reason you should use the @ operator is when you are attempting to load files externally to your file system, or within try and catch statements.

The basic try and catch statement

We can handle errors by using a try and catch statement. We try and execute some code, and catch any errors which may occur. Let’s have a quick look at the basic syntax.

<?PHP
echo('<h1>Try and catch exercise</h1>');
 
try {
    throw new Exception('I do not want my password revealed!');
    echo('<p>My password is: php_is_great</p>');
} catch(Exception $e) {
    echo('<p>An error occurred: ' . $e -> getMessage() . '</p>');
}

When you run this, you will get the following:

<h1>Try and catch exercise</h1>
<p>An error occurred: I do not want my password revealed!</p>

You can see that line 6 is never executed because we threw an error—we told the PHP engine that an error had occurred on line 5. As the error occurred in a try statement, it will attempt to catch any errors. On line 5 we threw the exception Exception, but this could have been anything as long as we define it as a valid Exception class.

Creating our own exception classes

Let’s try a simple scenario where one needs a certain type of input, and will reject everything else. A simple example would be a cup of coffee. To make a refreshing cup, one needs to use boiling water, not cold water. Lets create a simple PHP class to simulate making a cup of coffee.

<?PHP
class Coffee
{
    private $waterTemperature = 0;
    private $poured = false;
 
    public function boilWater($temperature) {
        $this -> waterTemperature = $temperature;
    }
 
    public function pourWater() {
        $this -> poured = true;
        echo('Ahhh. A nice cup of coffee.');
    }
}
 
$myCoffee = new Coffee();
$myCoffee -> boilWater(10);
$myCoffee -> pourWater();

With this code, we are susceptible to a cold cup of coffee. At the moment we are only boiling the water to 10 degrees Celsius, which is nowhere near hot enough—we will be pouring ourselves a cold cup of coffee! So let’s make a few amendments so this tragedy will never arise.

<?PHP
class ColdWaterException extends Exception
{
    public function __construct($message) {
        parent::__construct($message, 0);
    }
 
    public function __toString() {
        echo('Error: ' . parent::getMessage());
    }
}
 
class Coffee
{
    private $waterTemperature = 0;
    private $minTemperature = 50;
 
    public function boilWater($temperature) {
        $this -> waterTemperature = $temperature;
    }
 
    public function pourWater() {
        try {
            $this -> checkTemperature();
            echo('Ahhh. A nice cup of coffee.');
        } catch(ColdWaterException $e) {
            $e -> __toString();
        }
    }
 
    private function checkTemperature() {
        if($this -> waterTemperature <= $this -> minTemperature) {
            throw new ColdWaterException('Water too cold.');
        }
    }
}
 
$myCoffee = new Coffee();
$myCoffee -> boilWater(49);
$myCoffee -> pourWater();

Explaining the code

As I said at the start, this may seem daunting. Read it through and try and understand what it is doing.

Read it through twice? Great. So, we first start off by creating the class ColdWaterException which will extend the Exception class. Try as you might, you will not be able to see the class in the above code. Why not? Well simply because it is built into PHP itself. All you need to know for now is that it is a good thing.

We have now created the custom exception class, extended the Exception class, so now it is time to populate it. As usual we will create the constructor method which will be called automatically when an instance is created. This takes one parameter called $message which is the error message we send. We call the parent::__construct() which does everything it needs to do in the Exception class which we don’t see.

So now the only thing left to do is to handle the error. This is where the function __toString() comes into play. The function is just to output the message you want to be seen, if any.

The Coffee class is quite similar to the original, with a few minor modifications. The first thing you might see is that there is another function, checkTemperature(). This function simply returns a ColdWaterException error if the temperature is below 50, since we want our coffee to be nice and hot. The pourWater() function uses the try and catch statement which we looked at earlier. If there is no exception then we echo out the success message, but if the statement has found a ColdWaterException then it will output the error message.

There are a few lines I would like to draw your attention to:

  • Line 26: notice that we use the name of the Exception we threw, not just Exception. We also set the error object to $e which we make use of on the following line.
  • Line 33: the most important line in the script. This is where we tell PHP that an exception has occurred.
  • Line 39: this is the line where we set the temperature. To try this out on your own, try setting this to different values.

Conclusion

I am going to do the conclusion slightly different and actually go back to the first block of code and explain why we didn’t use exception handling on it. Let’s first recap on the code:

<?PHP
$a = Array("foo", "bar", "foobar");
$b = 10;
$c = $a + $b;
echo($c);

We can make this code parse by adding five extra characters. All we need to do it tell PHP that $a is an integer and not an array. “Ahh, of course” I can hear you say, “… but how can we do that?”. The answer is type casting. Type casting requires that you put the name of the data type you want to turn the value into at the start in brackets. Let’s look at it in this example.

<?PHP
$a = Array("foo", "bar", "foobar");
$b = 10;
$c = (int)$a + $b;
echo($c);

Run this code and you will see the output as 11. That’s right, 11. Not 10. The reason is that $a is not null, it contains a value, so it returns when cast as an integer the value 1. The reason for this small example is just to let you know that exception handling shouldn’t be used every time a error might occur—there are sometimes better ways.

Date posted June 8th, 2007
Comments Disabled
Categories PHP
Author Christopher Hill

I'm Christopher. A twenty-something graduate, star gazer, aspiring triathlete, vegetarian, reader and writer, cinemaniac and lover of life in general

From the journal

From the deep

Obligatory links

Create simple UML diagrams on-the-fly

yUML is an online tool for creating and publishing simple UML diagrams. It’s makes it really easy for you to: Embed UML diagrams in blogs, emails and wikis, Post UML diagrams in forums and blog comments, Use directly within your web based bug tracking tool and Copy and paste UML diagrams into MS Word documents and Powerpoint presentations.

Javascript Tidy

One thing I often need to do is to tidy javascript from it’s packed state. Often to fix the developers bugs, add new features or to modify it slightly. I give you, the Javascript Tidy, a tool I couldn’t live without.

jQuery Slider plugin (Safari style)

A pretty awesome slider. Haven’t tried it out yet but the new version seems pretty easy to skin, so you can style it however-the-hell you want (note: click the ‘jQuery Slider update’ link).

MySQL Format Date

MySQL Format Date helps you format your dates using the MySQL DATE_FORMAT function. Just select a common date format and then change it to your suit your needs. The MySQL DATE_FORMAT code will be generated at the bottom of the page which you can then copy into your query.

The future of wireframes?

I have a love hate relationship with wireframes. In the last 10 years they’ve been a part of every web project I’ve worked on. There have been times when I can’t imagine how we would have solved a particular problem without them. Yet there are also times when I’ve been completely exasperated at the amount of time and energy they’ve consumed, seemingly to very little reward.

So you need a typeface?

A pretty humorous look into how you could choose your typeface for your next project.

New global visual language for BBC

We decided to embark on an ambitious project, called Global Visual Language 2.0, with the aim of unifying the visual and interaction design of bbc.co.uk and the mobile website.

jQuery plugin: Nivo Slider

A really cool image slider than has some unique transitional effects without using Flash.

MooTools plugin: DatePicker

jQuery has the best functioning plugins. MooTools has the best looking plugins. Whenever I want to add in a datepicker I always find this and think: “Oooh. Pretty. Do want.”. Then realise it’s MooTools only. Real shame.

jQuery plugin: Sparklines

I know, I know. This plugin has been around for, what seems like, years. But I thought I would give it a little bit of a spotlight. And yes, so I can easily find it again.

jQuery plugin: asmSelect

asmSelect is a jQuery plugin providing progressive enhancement to select multiple form elements. It provides a simpler alternative with several advantages. This new version includes several bug fixes and enhancements.

How coupon codes can lead to lost revenue

In this post we’ll be looking at how coupon codes (used synonymously here with promo and discount codes) can cause retailers to lose revenue. I’ll share some (hopefully) interesting trends that I’m seeing with a client I work with, and hopefully start a discussion with how to turn lost revenue into gained revenue.

A good browser should be able to reproduce itself

This is an interesting project which aimes to completely reproduce the visual aspect of Safari in pure HTML+CSS with zero images. There are a few caveats at the moment, such as no refresh button, but they say they are working on it. Once again this really shows the power that HTML5 and CSS3 brings to the Web.

jQuery plugin: gameQuery

gameQuery is a jQuery plug-in to help make javascript game development easier by adding some simple game-related classes. It’s still in an early stage of development and may change a lot in future versions.

CSS/Javascript Word Clock

A lit­tle ex­per­i­ment I built: a word clock using CSS3 trans­forms and a lit­tle Javascript to run the ac­tu­al clock. Use­ful? Maybe not. Fun? Def­i­nite­ly.

CSS Border Radius Web Page

It’s one of those things that makes you think “Doh! I should have made that agaes ago”. A simple Web page that allows you to simply get the CSS for the exact border radius you want.

The main thing is not to install Flash

A security expert who has won the Pwn2Own contest for 2 years running said, basically, that Flash is insecure. Well, we all knew that which is why we add Flashblock and the like. Right?

Pure CSS3 Bokeh effect

One of the best apps made using CSS3, that’s for sure. A few more options would be nice, such as changing colours of the circles and being able to place them manually.

EZ-CSS: An easy to use, lightweight, CSS framework

It is light (1kb), flexible, browser-friendly and easy to use! ez-css is a different kind of CSS framework. Authors are not bound to a “grid”. Plus, columns and gutters can be of any width.

jQuery plugin: Quicksand

I love Mac apps, especially for their attention to detail. CoreAnimation makes it so easy to create useful and eye-pleasing effects. Quicksand aims at providing a similar experience for users on the web.