When to use exception handling for website

Hi,

I’ve been reading about exception handling in PHP. The logic of it looks very simple yet I’m confused as to when/how to use it in a website context. From what I can see the advantages are:

  • Throwing multiple exceptions results in more concise code compared to loads of if/elses
  • A thrown exception can be caught outside of the function that threw it
  • You can throw multiple exceptions and only need to catch it once (though you don’t have to)
  • It makes use of internal PHP error reporting functionality since you can set error codes and messages and get file, line and trace
  • You can extend the Exception class

However, it seems to be there is little need for this in a website. I can see in a standard desktop application that is running constantly exceptions need to be handled and dealt with. Let’s say I connect to a database and program it so separate exceptions are thrown for 1. Can’t connect, 2. Can’t set charset, 3. Can’t select database

If any of these exceptions occur, the website is (usually) useless anyway so why not just do some error logging then and exit() or die()?

A few further questions:

  • In a website, when should it be used? Surely it is not meant for validation. For example, if I am expecting a page number as a GET var, aren’t I better off casting it as an int and then checking it is not negative?
  • If the script cannot continue due to a certain exception (e.g. database error as above), should you leave the exception uncaught so it stops the script? (And perform any error logging via set_exception_handler)
  • Is there ever a need to use exception handling with set_error_handler?

Can someone please help clarify this? Thanks.

In my opinion exceptions are not useless, the following doesn’t crash the website:

// Fetch the three most recent pages:
try {
	
	$query = 'Select id, title, content, DATE_FORMAT(dateUpdated, "%e %M %Y") as dateUpdated FROM pages ORDER BY dateAdded DESC LIMIT 3';
	$result = $pdo->query($query);
	
	// Check that rows were returned:
	if ($result && $result->rowCount() > 0) {
		
		// Set the fetch mode:
		$result->setFetchMode(PDO::FETCH_CLASS, 'Page');
		
		// Records will be fetched in the view:
		include('views/index.html');
		
	} else { // Problem!
		throw new Exception('No content is available to be viewed at this time');
	}
	
} catch(Exception $e) { // Catch generic exceptions
	include('views/error.html');
}
<!-- # error.html  -->
<section class="fullWidth">
	<article>
     	<h1>An Error Occurred!</h1>
          <p>The content is not viewable because of an error occurred. We apologize for any inconvenience. The system administrator has been notified and will correct the problem as soon as possible</p>
		<p>Details (not for public consumption): <span class="error"><?php echo $e->getMessage(); ?></span></p>
	</article>
</section>     

Yes, but why not just go:

// Fetch the three most recent pages:

$query = 'Select id, title, content, DATE_FORMAT(dateUpdated, "%e %M %Y") as dateUpdated FROM pages ORDER BY dateAdded DESC LIMIT 3';
$result = $pdo->query($query);

// Check that rows were returned:
if ($result && $result->rowCount() > 0) {

    // Set the fetch mode:
    $result->setFetchMode(PDO::FETCH_CLASS, 'Page');

    // Records will be fetched in the view:
    include('views/index.html');

} else { // Problem!
    include('views/error.html');
}

Off the top of my head that you could send (email) the error to the administrator from the exception or an error log, where unless notified by someone or is monitor daily wouldn’t know about it. On a small site probably wouldn’t be worth it, but on a large site it probably would.

set_error_handler() is often used in frameworks to turn php errors into exceptions.

Exceptions allow you deal with what might otherwise be unrecoverable errors. If a database query fails because of a duplicate id for example, you don’t want your end users seeing the error (plus, error messages can often expose details about your app that might be useful to someone trying to hack it) - instead, you can catch the exception, log it, and display a more friendly message and allow the user to take a different course of action.

One good benefit, in my eyes, is that it allows you to deal with the error anywhere in your calling code, not just in the code that directly calls the method/function that throws the exception - the exception will continue up the chain, until it’s caught (or not, as the case may be). This gives you more control about where you choose to put your exception handling code - you don’t have to manually pass errors back up the stack.

Thanks, I think I’m getting it now. Is this a good case for exception handling?

  1. If can’t connect to database, throw exception
  2. If can’t select database, throw exception
  3. If can’t set charset, throw exception

Try all three and perform only a single catch. Given that I regard all three are enough to kill the script I simply log the error message, code, line number, etc to a file and display a “The database is currently down, please come back later” type message.

My second example, is not one that kills the script. I am trying to write to a file that should already exist.

  1. If the file does not exist, throw exception
  2. If the file is not writable, throw exception

Again, I only need to catch it once so the code is tidier than if/else. In each case, I can display an error message and insert it into an unwritable database and carry on as usual.

Are these both good use cases?

So from what I can see so far exceptions are good because:

  1. You can add lots of exceptions in your code and only catch once
  2. You can catch anytime between it getting thrown and the end of the script
  3. The Exception class allows you to create custom error codes/message and get the trace/file/line
  4. You can extend the Exception class for more customised error reporting

And it shouldn’t be used for general validation (form validation, numbers being out of range, etc).

Finally, is set_error_handler() a good idea? Seem a bit lazy in a global kind of way. :wink:

I guess also, if you have a bootstrap there might be loads of things that could generate an error that warrants killing the script and you could do it all in a single try/catch.

Thanks.

Yeah I think I’d agree with your use of exceptions in those scenarios.

I think it depends on the context. If you’re calling a validate() method on an object, then you could just return true or false for example, but if you’re calling a save() or update() method on your object, then you’d probably want to throw an exception if the data is not valid.

There is always the risk that your code might cause php to throw an unexpected error which would kill your script and won’t look very professional to the end user (not to mention it might expose information that could compromise your system).

By setting an error handler you can catch these errors and do something about them. It’s quite common practice to use this method to convert PHP errors into exceptions which can then be caught locally if you want, but you can also use [fphp]set_exception_handler[/fphp] to set a global handler to catch any exceptions that you hadn’t planned for.

Thanks for that.

This may be a stupid question but if you have something like:

function foo() {

    throw new Exception("Whatever");

    echo "End of foo function";

}

try {

    foo();

}
catch (Exception $e) {

    // Return back here?

}

Is there any way to return back to where the exception was thrown and get End of foo function to echo?

Not as far as I know. If foo should still return an output or do some work even in the event of an error that occurs in part of foo’s code, then I think you don’t really want to be throwing an exception in this case. If the error occurs in a sub-function called from foo, then you could just move your try/catch block inside foo.

Great, thanks!