Advice on Improving Error-Handler

This is a vague question, but I am wondering if you guys can offer some advice on designing a better Error-Handler?! :-/

Here is what I have now…

In each script, my Error-Handling Code looks like this…


	// ************************
	// Check Section Format.	*
	// ************************
	$validSections = array("finance", "legal", "management", "small-business", "xxx");

	if (in_array($_GET['section'], $validSections, FALSE)){
		// Valid Section Format.
		// Continue processing things...

	}else{
		// Invalid Section Format.
		$_SESSION['resultsCode'] = 'ARTICLE_INDEX_SECTION_NOT_FOUND_2421';

		// Set Error Source.
		$_SESSION['errorPage'] = $_SERVER['SCRIPT_NAME'];

		// Redirect to Display Outcome.
		header("Location: " . BASE_URL . "/account/results.php");

		// End script.
		exit();
	}//End of CHECK SECTION FORMAT

Then my “results.php” script does the following…

  • Displays an Error Message to the User
  • Logs the Error into a Database Table
  • Emails the Admin if the Error could not be written to the Database
  • Emails the Admin with a similar Error Message so he/she can stay informed of User/System Errors

For the Error Messages, I just use a gigantic Case statement like this…


	// Invalid Section Format.
	case 'ARTICLE_INDEX_SECTION_NOT_FOUND_2421':
		echo '<h1>Section Not Found</h1>';
		echo '<p>The Section you chose cannot be found. (2421)</p>';
		echo '<a class="button" href="' . BASE_URL . '/">Return to Home Page</a>';
		break;

Any thoughts or suggestions?

(BTW, I am still stuck with Procedural Code for now, so please don’t offer any OOP suggestions as that’s over my head for now?!)

Sincerely,

Debbie

First step to improving it would be to abstract the call.

You could do something like this:

if (…) {

} else {
log_error(ARTICLE_INDEX_SECTION_NOT_FOUND_2421,$_SERVER[‘SCRIPT_NAME’]);
}

This allows you to change what happens in the error logging globally. Things like exit() might not be necessary in some reports, therefore hard coding is a bad practice.

So I guess you are saying to stop using the SESSION to pass things?

And it also looks like I would need to create a Function, and “include” it in every script?

Debbie

Should I break things out into different Functions?

Like mentioned in my OP, there are a few things I do…

1.) Display either an “Error Message” (or “Success Message”) after more actions
2.) Log the Error/Success into the Database
3.) E-mail the Error/Success to the Admin
4.) E-mail the Admin if the Error cannot be logged.

#1 should always occur.

For #2, I always want to log any “Errors”, but I’m not sure if I should also log “Success Messages”?! :-/

For #3, I think I should just e-mail the Admin if there is an “Error”.

#4 should always happen if applicable.

Sincerely,

Debbie

And it also looks like I would need to create a Function, and “include” it in every script?

If you use PHP5, you can take advantage of autoloading so you don’t have to include it manually.

Should I break things out into different Functions?

You should be using a single wrapper function to do the initial logging. What happens within this function could be broken down depending on what and why the logger was called and how complex it is.

Okay, some follow-up questions/concerns…

1.) If I am in “Script A”, and I include “Script B”, then is it correct that all variables in “Script A” can be seen in “Script B”, and that all variables in “Script B” can be seen in “Script A”?

2.) My “results.php” script is 2,141 lines long… Most of that is code like this…


	// Message Sent.
	case 'REPLY_MESSAGE_SENT_2193':
		echo '<h1>Message Sent</h1>';
		echo '<p>Congratulations!</p>';
		echo '<p>Your Response has been sent. (2193)</p>';
		echo '<a class="button" href="' . BASE_URL . '/account/messages/incoming">Return to Messages</a>';
		break;

It seems like that is quite a bit to put into a Function nested in my “utilities/function.php” script…

3.) As I randomly scan through my various Errors, I notice that often I am passing a different set of values to my “results.php” script.

A “standard” call to “results.php” would look like this…


	}else{
		// Section Not found in URL.
		$_SESSION['resultsCode'] = 'ARTICLE_INDEX_NO_QUERY_STRING_2422';

		// Set Error Source.
		$_SESSION['errorPage'] = $_SERVER['SCRIPT_NAME'];

		// Redirect to Display Outcome.
		header("Location: " . BASE_URL . "/account/results.php");

		// End script.
		exit();

	}//End of ATTEMPT TO RETRIEVE ARTICLES

However, I am often passing other values to customize my Error Messages like this…


	// Verify Insert.
	if (mysqli_stmt_affected_rows($stmt3)==1){
		// Insert Succeeded.
		$_SESSION['resultsCode'] = 'COMMENT_MEMBER_COMMENT_ADDED_2052';

// LOOK HERE ===>
		// Set values for Success Message.
		$_SESSION['firstName'] = $firstName;
		$_SESSION['heading'] = $heading;

		// Notify Other Subscribed Members
		notifySubscribersOfNewComment($dbc, $articleID, $commentID, $sessMemberID);

	}else{
		// Insert Failed.
		$_SESSION['resultsCode'] = 'COMMENT_MEMBER_COMMENT_FAILED_2053';

	}// End of VERIFY INSERT.


	// Set Error Source.
	$_SESSION['errorPage'] = $_SERVER['SCRIPT_NAME'];

	// Redirect to Display Outcome.
	header("Location: " . BASE_URL . "/account/results.php");

	// End script.
	exit();

So my question here is, “How could I write a Function that would adjust to handle a varying number of arguments?”

4.) I always want to log messages in my database, whether they are “Error Messages” or “Success Messages”.

HOWEVER, at this time, I only want to e-mail the Administrator if there is an “Error Message”.

So, do I need another argument/parameter that tells my “results.php” script - or maybe a new Function - whether or not it should also e-mail the Admin?

Maybe something like this…


	log_error($errorCode, $scriptName, $emailAdmin=FALSE){

	}

Sorry for all of the questions, but I’m really not sure how to create a more sophisticated Error-Handler?!

Thanks,

Debbie

It sounds like you’re looking to handle logging strategies, and not logging per se. Take a look at https://github.com/Seldaek/monolog and it’s documentation it should’nt be too hard to implement a globally available wrapper for it in your application.