Tutorial Details
- Topic: PHP Exceptions
- Version: PHP 5 and above
- Difficulty: Beginner - Intermediate
- Estimated Completion Time: 1 Hour
Still returning false whenever a function in your program fails? In this article, we’ll learn about PHP exceptions, and how you can use them to soup up your application’s error handling.
Introduction
What are exceptions?
Exceptions are special conditions, usually errors, that can occur or be explicitly made by a program. They connote that something entirely different from what was expected has occurred. In most cases, the situation requires that a special instruction set be done in order to mitigate a catastrophic system failure.
How do we use exceptions?
Exceptions can be thrown and caught. When an exception is thrown, it means that something out of the ordinary has happened, and it will require another function to do something else. Catching an exception is the function telling the rest of the program, “Hey, I can handle this exception, let me at it!”
Exceptions can be explained by using the analogy of a baseball game.
- The pitcher (Bowser) throws a baseball to the catcher.
- The batter (Mario) tries to hit the ball. If he’s not able to do it, he gets a strike. If he’s able to do it, a fielder (either Donkey Kong or Waluigi) has to catch it.
- If Donkey Kong catches the ball, he then has two choices: if he’s not close enough, he can throw it to another fielder; or if he’s close enough, he can throw it to a baseman and tag Mario to get an out.
In exceptions, the pitcher throwing a baseball to the catcher is like a function running normally.
But when the batter hits the ball, something “exceptional” happens, and certain routines need to be done.
A fielder catching the baseball is like a try-catch function getting the exception. This try-catch function can now either handle the exception, or throw it for another try-catch function to handle. Whichever try-catch function can handle the exception is the one that finally does something.
Using PHP Exceptions
It’s really simple to implement exceptions in PHP. Since exceptions are part of the Standard PHP Library or SPL, they’re part of PHP core as long as you’re running PHP 5 and above. Exceptions are already there, just longing and waiting to be used.
Exceptions are instantiated the same way as objects:
$exception = new Exception(); throw $exception;
Much like objects, they also have methods that can be called. These methods make it easier for a try-catch function to react to exceptions. For example, the getMessage() function will let you get an exception’s error message, which you can then log or show on the browser.
Here’s a list of an exception’s methods:
getMessage()– gets the exception’s messagegetCode()– returns a numerical code that represents the exceptiongetFile()– returns the file where the exception was throwngetLine()– returns the line number in the file where the exception was throwngetTrace()– returns the an array of the backtrace() before the exception was throwngetPrevious()– returns the exception thrown before the current one, if anygetTraceAsString()– returns the backtrace() of an exception as a string instead of an array__toString()– returns the whole exception as a string. Isoverrideable.
To better illustrate these methods, let’s create a User class that does basic user record management:
<?php
class User
{
protected $_user_id;
protected $_user_email;
protected $_user_password;
public function __construct($user_id)
{
$user_record = self::_getUserRecord($user_id);
$this->_user_id = $user_record['id'];
$this->_user_email = $user_record['email'];
$this->_user_password = $user_record['password'];
}
//we'll fill these in later
public function __get($value) {}
public function __set($name, $value) {}
private static function _getUserRecord($user_id)
{
//For this tutorial, we'll use a mock-up record to represent retrieving the record
//from the database and returning the data
$user_record = array();
switch($user_id) {
case 1:
$user_record['id'] = 1;
$user_record['email'] = 'nikko@example.com';
$user_record['password'] = 'i like croissants';
break;
case 2:
$user_record['id'] = 2;
$user_record['email'] = 'john@example.com';
$user_record['password'] = 'me too!';
break;
case 'error':
//simulates an unknown exception from whatever SQL library is being used:
throw new Exception('An error from the SQL library!');
break;
}
return $user_record;
}
}
?>
In this example, there are several places where something exceptional could happen. For starters, the $user_id input in our _getUserRecord() function should be an integer. In the event that it’s not, we should throw an exception:
...
...
...
private static function _getUserRecord($user_id)
{
$user_id = self::_validateUserId($user_id);
...
...
...
}
private static function _validateUserId($user_id)
{
if( !is_numeric($user_id) && $user_id != 'error' ) {
throw new Exception('Whoa! I think there\'s something wrong with the user id');
}
return $user_id;
}
Let’s try it out by instantiating our User class with an invalid parameter:
//First try getting our user numero uno
$user = new User(1);
//Then, let's try to get the exception
$user2 = new User('not numeric');
You should get an error like this:

Uncaught exception error message
Now, let’s have Donkey Kong catch this exception.
try {
//First try getting our user numero uno
$user = new User(1);
//Then, let's try to get the exception
$user2 = new User('not numeric');
} catch( Exception $e ) {
echo "Donkey Kong has caught an exception: {$e->getMessage()}";
}
Let’s run it again, this time with our try-catch function:

Thanks Donkey Kong!
As you can see, with Donkey Kong catching our exceptions, we were able to suppress the awful error messages thrown by PHP when an exception is uncaught.
One thing to note here is that when an exception is thrown, it only stops when a try-catch function is able to catch it. Otherwise, it will remain uncaught, keep climbing up the trace of the function call, and be displayed as an error on the browser. In our current example, let’s trace where our exception gets thrown:
- Create a new
Userobject on the$user2 = new User('not numeric');line - Run the
__construct()function of theUserclass - Go to the
_getUserRecord()function of theUserclass - Validate the
$user_idusing the_validateUserIdfunction - If the
$user_idis not numeric, throw a new Exception object
We can also run the getTraceAsString() function to get the trace of the exception, which will give us the exact same thing:
...
...
} catch( Exception $e ) {
echo "Donkey Kong has caught an exception: {$e->getMessage()}";
echo '<pre>';
echo $e->getTraceAsString();
echo '</pre>';
}

getTraceAsString() results
As you can see, even if the exception is thrown deep inside the trace of $user2 = new User('not numeric'), it keeps climbing up until it gets caught in the try-catch block on the top-most level.
Now, let’s construct our exception to use a code. Associating a code number with an exception is a good way of hiding the error from the client. By default, the code number of an exception is 0, but we can override this whenever we create a new exception:
...
...
...
if( !is_numeric($user_id) ) {
throw new Exception('Whoa! I think there\'s something wrong with the user id', UserErrors::INVALIDID);
}
...
...
...
Don’t forget to create our UserErrors class:
class UserErrors
{
const INVALIDID = 10001;
const INVALIDEMAIL = 10002;
const INVALIDPW = 10003;
const DOESNOTEXIST = 10004;
const NOTASETTING = 10005;
const UNEXPECTEDERROR = 10006;
public static function getErrorMessage($code)
{
switch($code) {
case self::INVALIDID:
return 'Whoa! I think there\'s something wrong with the user id';
break;
case self::INVALIDEMAIL:
return 'The email is invalid!';
break;
case self::INVALIDPW:
return 'The password is shorter than 4 characters!';
break;
case self::DOESNOTEXIST:
return 'That user does not exist!';
break;
case self::NOTASETTING:
return 'That setting does not exist!';
break;
case self::UNEXPECTEDERROR:
default:
return 'An unexpected error has occurred';
break;
}
}
}
We can then modify our exception handler to display the exception code instead of displaying the message:
...
...
} catch( Exception $e ) {
echo "Donkey Kong has caught an exception with code: #{$e->getCode()}";
}
It should result in this:
Now, let’s use all the other methods of an exception by trying to log the exception. First off, let’s create our Logger class:
class Logger
{
public static function newMessage(
Exception $exception,
$clear = false,
$error_file = 'exceptions_log.html'
) {
$message = $exception->getMessage();
$code = $exception->getCode();
$file = $exception->getFile();
$line = $exception->getLine();
$trace = $exception->getTraceAsString();
$date = date('M d, Y h:iA');
$log_message = "<h3>Exception information:</h3>
<p>
<strong>Date:</strong> {$date}
</p>
<p>
<strong>Message:</strong> {$message}
</p>
<p>
<strong>Code:</strong> {$code}
</p>
<p>
<strong>File:</strong> {$file}
</p>
<p>
<strong>Line:</strong> {$line}
</p>
<h3>Stack trace:</h3>
<pre>{$trace}
</pre>
<br />
<hr /><br /><br />";
if( is_file($error_file) === false ) {
file_put_contents($error_file, '');
}
if( $clear ) {
$content = '';
} else {
$content = file_get_contents($error_file);
}
file_put_contents($error_file, $log_message . $content);
}
}
We’ll have to modify our exception handler to use the Logger class:
...
...
} catch( Exception $e ) {
echo "Donkey Kong has caught an exception with code: #{$e->getCode()}";
Logger::newMessage($e);
}
Now, when we run our program again, it should just display the exception code. We can then open the exceptions_log.html file and we’ll see the log of exceptions we’re getting:
Congratulations! You now have working knowledge on how to implement basic PHP Exceptions. Now, let’s move on to more advanced stuff!
Extending Exceptions
Even at their most basic level, exceptions are already an essential tool for error handling in applications. By extending exceptions, however, we can create our own customized exceptions and take our application’s exception handling to the next level.

The next level is THIS much fun.
To create a custom exception, we’ll need to create our own exception class, extending the Exception class. Let’s create a custom UserException for our user class:
class UserException extends Exception
{
public function __construct($error_code)
{
parent::__construct(UserErrors::getErrorMessage($error_code), $error_code);
Logger::newMessage($this);
}
}
As you can see, we overrode the __construct function to implement our own constructor. Since we extended the Exception object, we’re still able to use the default Exception constructor by using the parent keyword. By doing this, we can skip providing an error message every time we throw an exception, and just provide an exception code. We can also skip having to log it ourselves, since the custom constructor is set up to automatically log the exception.
Let’s update our code to use the new UserException class:
private static function _validateUserId($user_id)
{
if( !is_numeric($user_id) && $user_id != 'error' ) {
throw new UserException(UserErrors::INVALIDID);
}
return $user_id;
}
Since the exception already automatically logs itself, we can skip logging it in our try-catch block:
...
...
} catch( Exception $e ) {
echo "Donkey Kong has caught an exception with code: #{$e->getCode()}";
//Logger::newMessage($e);
}
Let’s also update the other places in our User class where we can expect exceptions.
User class:
...
...
...
public function __get($value) {
$value = "_{$value}";
if( !isset($this->$value) ) {
throw new UserException(UserErrors::NOTASETTING);
}
return $this->$value;
}
public function __set($name, $value) {
switch($name) {
case 'user_id':
$user_id = self::_validateUserId($value);
$this->_user_id = $user_id;
break;
case 'user_email':
$user_email = self::_validateUserEmail($value);
$this->_user_email = $user_email;
break;
case 'user_password':
$user_password = self::_validateUserPassword($value);
$this->_user_password = $user_password;
break;
default:
throw new UserException(UserErrors::NOTASETTING);
break;
}
return true;
}
private static function _getUserRecord($user_id)
{
...
...
...
switch($user_id) {
...
...
...
default:
throw new UserException(UserErrors::DOESNOTEXIST);
break;
}
}
Now let’s try triggering these exceptions:
$user = new User(1);
try {
$user->user_email = 'invalid email';
} catch( Exception $e ) {
echo "Donkey Kong has caught an exception with code: #{$e->getCode()}<br />";
}
try {
echo $user->setting_that_doesnt_exist;
} catch( Exception $e ) {
echo "Donkey Kong has caught an exception with code: #{$e->getCode()}<br />";
}
try {
//user id that doesn't exist
$user = new User(3);
} catch( Exception $e ) {
echo "Donkey Kong has caught an exception with code: #{$e->getCode()}<br />";
}
We should get something like this:
You’re probably wondering — besides custom constructors, what benefits can we get from custom exceptions? It would be relatively simple to just use the default Exception class. But by using a custom exception, we can:
- Override the
__constructfunction and implement our own - Organize our exceptions by the type of object they are
- And the best one of all: Use multiple catch blocks and catch different kinds of exceptions depending on type!
Multiple Catch Blocks
By using multiple catch blocks, we are able to catch specific types of exceptions. This can be useful since we can indicate what to do when different kinds of exceptions occur. Currently, our try-catch functions catch the regular Exception type exceptions — this allows us to provide a fail-safe catch block for exceptions of types that have not been planned for.
With that in mind, let’s create a try-catch function that will catch our custom exception, UserException, and do something different about it. Let’s also use another catch block to make sure that any other unexpected exceptions that are thrown will still be caught.
try {
$user = new User(1);
$user->user_password = '123';
} catch( UserException $e ) {
echo "Donkey Kong has caught a User Exception with code: #{$e->getCode()}<br />";
} catch( Exception $e ) {
echo "Donkey Kong has caught a Exception with code: #{$e->getCode()}<br />";
}
try {
//when we use 'error' as the argument, the User class will simulate an
//unexpected exception from the SQL library
$user = new User('error');
} catch( UserException $e ) {
echo "Donkey Kong has caught a User Exception with code: #{$e->getCode()}<br />";
} catch( Exception $e ) {
echo "Donkey Kong has caught a Exception with code: #{$e->getCode()}<br />";
}
We should see the following output:
We can clearly see that the UserException and the regular Exception were handled differently, since they have different messages. It may not seem useful right now, but imagine being able to log only certain exceptions, or even create a custom exception called DisplayableException, which we can set so that they’re the only ones that users will be able to see.
Conclusion
With the power of PHP exceptions, we can simply and easily handle different kinds of errors. Hopefully, with the help of this tutorial, you’ll be able to build from our simple example and create an even more effective way of handling your application’s errors through PHP exceptions.
Do you use exceptions in your applications? What kind of exceptions do you use? Let me know in the comments!









It appears you’ve turned what could have been a semi decent article into a meme ridden post, which seems to be aimed at adolescent meme obsessed interwebz.
Y U NO TAKE IT SERIOUSLY?
When I first wrote the article without the jokes, it was seriously boring as hell. I was hoping the added humor made it easier to digest.
Besides, I only used like two meme’s in the article. I can’t see how it’s “ridden” with memes.
I thought the humor made the article easier to read. I think humor in any article like this helps. “Some Dude” is wrong.
I enjoyed seeing Mario appearing in what would otherwise have been a very dry topic. I came here looking for a way to replace PHP’s error handling system with exceptions, btw.
Some Dude = Idiot.
Nice article.
Have you done any speed tests with exceptions?
I did that a while back, check out http://forrst.com/posts/Speed_performance_of_Trying_and_catching_Excepti-Ox3
Bottom line: it’s actually no slower, only when an exception is created is there noticable added overhead. Only when an exception is created is there a bit of slowdown, though negligable in most cases.
@Nikko: awesome tut, good to see Exceptions getting some attention finally in the PHP world.
Speed doesn’t matter if you have a great way to find out what happened when your client screams “It doesn’t work” .
Very nice article
Agree why we bother much with speed if we can deliver product with clear exception process. We only need to upgrade the hardware.
I think the convenience and maintainability obtained by using exceptions greatly outweigh the performance hit you get when using exceptions. Having a standard operating procedure when it comes to errors in an application is a very effective way of making it easier for developers to work on a big project.
Haha, nice sense of humor! I only forgot to read the text :P. Good article though.
you do know that soup is something you eat, right? you should have put “supe” (meaning to speed up). that being said, nice article. the rest was great.
I was actually a bit torn up with that – researched high and low and got a lot of conflicting definitions for “soup-up” :)
Thanks for reading the article!
Nice article gotta say love the way u mixed humor with it, i hope you keep the Humor and the tutorials up. 5 points for using Barney stinson.
You know it’s going to be legendary when Barney Stinson’s in it. High five!
Thank you for building your blog site, I located you on Google and I need to say I’m impressed.
Appreciate it yet again…
Great post! Congratulations!
Good examples for the subject.
5 points for using Barney stinson [2] .
Thanks! High five! [2]
This was a great article. It clarified a lot about errors that I’m still pretty new to. The only thing I’m really struggling with here is that there seems to be very few times where I’d actually want to output errors to the end user. Most of the time I just want the script to stop and output a message letting the user know that there was an error. The detailed errors are really only for developers anyway, so why go through the time to put together a long and arduous error class that only makes it easier for ME to read?
Maybe you could give a follow up with a real world example of where you would use this and have the time be worth it?
This was a great article. It clarified a lot about errors that I’m still pretty new to. The only thing I’m really struggling with here is that there seems to be very few times where I’d actually want to output errors to the end user. Most of the time I just want the script to stop and output a message letting the user know that there was an error. The detailed errors are really only for developers anyway, so why go through the time to put together a long and arduous error class that only makes it easier for ME to read?
Maybe you could give a follow up with a real world example of where you would use this and have the time be worth it?
It really depends on how open you want to be with your users regarding errors. There are times that you’ll use exceptions to make sure that user actions are done correctly, and if not, it’s better to give them a good error message explaining what happened as opposed to just telling them something went wrong.
For example, you could create a custom “DisplayableException” exception which is an exception that can be displayed to the user directly.
After catching your error exceptions, you can rethrow another DisplayableException for your users.
Maybe something like this:
try {
$someClass->doSomeAction();
} catch( Exception $e ) {
Logger::log($e);
throw new DisplayableException(‘X has happened because of Y, please try doing Z to fix it.’);
}
And then, DisplayableExceptions can be caught (or you can register a default error handler so you don’t have to catch all of them), and you should be able to facilitate better error reporting for your user.
Whoops, didn’t mean to repeat what you said, I copy-pasted your comment so I wouldn’t have to keep on scrolling up to look at your comment. Must’ve forgotten to remove it, heh.
Probably is me getting old & bitter, but I felt like I was browsing one of those cheap tutorial sites with non relevant images all over the place, I usually come here for tutorials and look at code, for humour I go to cracked.com…
exception = goto
Another thing to look at is having a default exception handler. You may not want to wrap try/catch blocks all over the place, and for the most part, when an exception happens, it’s going to break the normal workflow of whatever’s going on (sure… there are exceptions to that as well – pun intended). But, you can create a default exception handler that can do your log message and display some screen to the user. Just an idea…
URL: http://php.net/manual/en/function.set-exception-handler.php
Hahahaha this was a VERY NICE article, and very funny to read.
Great work!
it was a funny way to explain something serious… :) thank u @Nikko!
Hi and sorry for not getting something right:
”
We can then modify our exception handler to display the exception code instead of displaying the message:
…
} catch( Exception $e ) {
echo “Donkey Kong has caught an exception with code: #{$e->getCode()}”;
}
”
How does “$e->getCode()” know about our “class UserErrors” to get the CONST code?
Where is the class UserErrors instantiated or passed?
Ah sorry now i got it. If an Exception is thrown in a try{} block, also a user defined Exception, this is automatically passed to the catch{} block via ($e)
Thank you! Very nice article for beginners and lazy proggers :)
:D Who cares about the exceptions, that comics are epic :D
Thanks for that! Excellent timing.
I’ve been building a logging class to display errors and development debug data to screen, console and/or file. The addition of exception handling should beef it up even more.
I recently completed a series on Errors vs Exceptions, which might be of some more help. It starts with error-handling basics in part 1, progresses to the conceptual need for exceptions in part 2, how to work with exceptions in part 3, and finally methodology in part 4, giving examples of default handlers.
http://anvilstudios.co.za/blog/php/error-vs-exception-part-1/
http://anvilstudios.co.za/blog/php/error-vs-exception-part-2/
http://anvilstudios.co.za/blog/php/error-vs-exception-part-3/
http://anvilstudios.co.za/blog/php/error-vs-exception-part-4/
Great Article, only if php would throw exceptions instead of default errors/warnings :/
@William:
Would be nice if PHP did this by default, but you can take care of that yourself by promoting all notices, warning, and errors to exceptions.
What the heck is this? “Exceptions for children”?
The analogies are retarded, sorry.
good article. worth reading
Thanks for the help on exceptions
I’m sorry but since I’m not currently browsing Reddit or 4chan I would really appreciate not to be scanning through 30+ idiotic, old and boring internet memes fully complete with images. This is the sort of stuff that makes me want to NOT scan what tutsplus is currently up to.
Nice,
Keep up the great work!
Thanks all for the kind replies! I know not all of you liked the humor in the article, but seriously, if you saw the first draft of this, it was boring as hell. I was hoping the humor would make it easier and fun to read, but I guess it’s not for everyone. Still, thanks again for reading it!
Is this a tutorial or a comic strip? Am I at the right website??
I would rather have a tutorial that is “boring as hell” than for it to be littered with stupid images every paragraph or two.
How in the world did this make it through the Nettuts editor review.
I didn’t mind the humour being in the article just the amount of it was a little over the top.
Thanks for this great tut.
Exception has enabled developers to handle errors in a more understanding way.
I have been looking for better ways to output and log errors using OOP but never found anything close to this, thanks for the great tutorial and detailed examples.
You can use set_exception_handler() to override the exception class with your userexception class.
Thanks for tut! Very nice article.
this is how it has to be… perfect tutorial… makes learning a looot easier…
thank u very much
Hey Nikko –
If you feel like adding some humour to an otherwise dry subject, then I say go right ahead.
It’s nice to see a bit of personality injected into tutorials on web design, development and coding.
Many Thanks,
Darren.
Humor was good. but a little less of it would be nice. Too much becomes too distracting. Just my thoughts. Useful article though; with or without humour. And you can always skip what you don’t like right?
agree
This is what i get Fatal error: Call to undefined method User::_validateUserEmail() in /Users/budiarsana/host/test.host/Exception/User.php on line 33
Thank you! This is exactly what i was looking for. Great, clean & crisp tutorial.
Nikko, your actually a legend. You seem to know your sh*t and the articles are great to read. Hope you don’t let the idiots around get to you.