Best Way to Handle Errors on a PHP Page

Best way to handle errors on a php page?

There are a lot of ways that you can deal with this and frankly none of them is intrinsically 'right'.

You will have to decide for yourself, which method is more 'comfortable' for you - it's always a mater of preferences (although there are certain techniques you should avoid and for good reasons).

It will highly depend on how you split your logic, however I tend to enclose all code that can return non-fatal errors inside a function, and use a return value of said function to indicate there was an error.

For fatal errors I tend to use exceptions (with try-catch blocks).

Now just to be clear:

  • A non-fatal error is an error that you can recover from - meaning that even though something went wrong, there is still some code that can be executed and generate some valuable output. For example if you wanted to get current time using NTP protocol, but the server didn't respond, you can decide to use local time function and still display a some valuable data to the user.
  • A fatal error is an error that you would not be able to recover from - meaning that something really bad happened and the only thing you can do is tell your user that page cannot do what it was asked to. For example if you were fetching some data from your database and got SQL Exception - there is no valuable data to be shown and you can only inform the user of this.

Non-Fatal Errors (using function return)

A good example of using function-returns as a way of dealing with non-fatal problems would be a function that is trying to display content of some file on the page when this is not the main objective of the page (for example you would have a function that displays badges, fetched from a text file, on every single page - I know that this is far fetched but bear with me).

function getBadge($file){
$f = fopen($file,'r');
if(!$f){
return null;
}
.. do some processing ..
return $badges;
}

$badges = getBadges('badges.txt');
if(!$badges){
echo "Cannot display badges.";
} else {
echo $badges;
}
.. carry on doing whatever page should be doing ..

In fact, the function fopen itself is an example of this - it will return.

Returns a file pointer resource on success, or FALSE on error.


Fatal-Errors (using exceptions - try-catch)

When you have some piece of code that needs to be executed because it's exactly what the user wanted (for example reading all news from database and displaying them to the user), you could use exceptions. Let's take a simple example - a user visited his profile and wanted to see all the messages he's got (let's assume, for now, that they are stored in plain text). You might have a function like:

function getMessages($user){
$messages = array();
$f = fopen("messages_$user.txt","r");
if(!$f){
throw new Exception("Could not read messages!");
}
... do some processing ...
return $messages;
}

And use it like this:

try{
..do some stuff..
$messages = getMessages($_SESSION['user'])); //assuming you store username in $_SESSION
foreach($messages as $msg){
echo $msg."<br/>";
}
} catch(Exception $e){
echo "Sorry, there was an error: ".$e->getMessage();
}

Now this could come in handy, if you had a 'top-level' script that would execute all the other code. That means that, for example, in your index.php you would just have:

try{
.. execute some code, perform some functions ..
} catch(Exception $e){
echo "Sorry, there was an error: ".$e->getMessage();
}

Do not overuse exceptions!

Whatever you do, never use exceptions as a way to check something you can recover from. Have a read on another question(full credit goes to Anton Gogolev for a very good explanation on this, as well as other answer-ers) as to why this is the case.

Further reading

Now there is no better way to learn how to deal with errors than to try several things and see what is good for you. You might find the below useful:

  • W3School on PHP Exception handling
  • Short tutorial on error handling(similar to my function-returns method)
  • Extensive tutorial on PHP error handling - including using trigger_error() function, which I haven't mentioned because I don't use it and don't know much about it, but apparently it's really useful. This is a particularly good read.

Hope this helps :)

Handling errors as exceptions. Best methods?

I usually install a global error handler to convert errors into exceptions:

function exceptions_error_handler($severity, $message, $filename, $lineno) {
if (error_reporting() == 0) {
return;
}
if (error_reporting() & $severity) {
throw new ErrorException($message, 0, $severity, $filename, $lineno);
}
}
set_error_handler('exceptions_error_handler');

For the rare cases, where I actually want to collect a bunch of warnings, I turn the above handler off temporarily. It's packed up nicely in a class:

/**
* Executes a callback and logs any errors.
*/
class errorhandler_LoggingCaller {
protected $errors = array();
function call($callback, $arguments = array()) {
set_error_handler(array($this, "onError"));
$orig_error_reporting = error_reporting(E_ALL);
try {
$result = call_user_func_array($callback, $arguments);
} catch (Exception $ex) {
restore_error_handler();
error_reporting($orig_error_reporting);
throw $ex;
}
restore_error_handler();
error_reporting($orig_error_reporting);
return $result;
}
function onError($severity, $message, $file = null, $line = null) {
$this->errors[] = $message;
}
function getErrors() {
return $this->errors;
}
function hasErrors() {
return count($this->errors) > 0;
}
}

Proper way to handle errors suppressed by @?

Mu. You should not set error_reporting to 0, even in production.

In development, you'll want to set the error reporting level to the highest possible to be notified about any and all errors or notices or deprecation messages or possible issues that may pose problems in the future.

In production, you'll want to set the error reporting level to only include errors and perhaps warnings, but not things like deprecation notices. This is to keep your error logs from superfluous information and be able to effectively track down production errors.

Because you should always log errors.

What you should not do in production is display errors on screen. That's what ini_set('display_errors', true|false) controls. You still want error reporting on production, just that that goes into a log file.

What is the correct way of handling errors and warnings on filesystem functions in PHP?

I think you want to want to set an errorhandler which throws exceptions:

function exception_error_handler($errno, $errstr, $errfile, $errline ) {
// see http://php.net/manual/en/class.errorexception.php
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}

set_error_handler("exception_error_handler");

Then your code would be:

try {
symlink(); // when an error occured, it jumps to the catch
} catch (ErrorException $ex) {
// do stuff with $ex
}

Best way to handle errors

Maybe you won't find my answer useful because I'm not a php developer, anyway I will try to give you common hints as error handling debates are common in any programming language.

1) First try to avoid the actual need for error handling. This does mean try to code in a way that error conditions are few as possible. A simple example: it's common sense that trying to clear an empty collection should not raise an error.

2) Distinct what is a supported failure than an unsupported one. A supported failure is an error condition that you actually want to track and handle as part of the program logic. An unsupported failure would be an error condition that's actually a code error. For example: you are trying to lookup an element in a map and it's part of the logic of your program that the specific element should be there. There's no sense to add code to test if the element was there and raise an error if it wasn't: you made the assumption it was there.

After you have understood these two points, I'm pretty sure you'll understand why exceptions are so useful to produce cleaner and more efficient code. The trick is: make your code to raise as few exceptions as possible (again: distinct supported and unsupported error conditions to choose what exceptions are actually needed) and catch them only at the most external scope, where the user of your application interact with it and 1)should be warned, 2)should decide what to do. Programmatically catch an excpetion without user interaction is, most of the times, a bad thing because it makes the dev think that catching exceptions is efficient just like conditionally do something (if-then-else) when an error condition arise when this is not the case. Exceptions won't cause any overhead to your application until they are thrown.

How should I approach error handling in PHP? Specifically user input

I have utilised comments below to come up with two individual functions for soft errors and returning user errors

For user errors:

function return_error($msg){
$_SESSION['error']=$msg;
header("location:javascript://history.go(-1)");
exit;
}

For soft errors / unusual behaviour (make_file() function just makes a file if not exist)

function soft_error($e){
$trace=debug_backtrace(-1);
if(isset($trace,$trace[0],$trace[0]['file'],$trace[0]['line'])){
$file=BASE_DIRECTORY.'logs/soft_error.log';
make_file($file);
$log=fopen($file,'a');
fwrite($log,'['.date('Y-m-d H:i:s').'] File: '.$trace[0]['file'].' - Line: '.$trace[0]['line'].' - Error: '.$e.PHP_EOL);
fclose($log);
}
}

For hard errors, there is error_log() or they will be logged automatically based on server settings, so that is fine



Related Topics



Leave a reply



Submit