Glad you learned something newDaedalus- wrote:You guys succeeded in doing something that hundreds of tutorials and web pages could not do:
You made me understand a design pattern. :p
New and improved error handling class!
Moderator: General Moderators
- Chris Corbyn
- Breakbeat Nuttzer
- Posts: 13098
- Joined: Wed Mar 24, 2004 7:57 am
- Location: Melbourne, Australia
- daedalus__
- DevNet Resident
- Posts: 1925
- Joined: Thu Feb 09, 2006 4:52 pm
try + catch is simple, and is my preference as you are raising individual exceptions, over categorised errors (e.g. E_USER_ERROR etc.)
In that example.. the MyClass object will, of course, always throw a DummyException, but in the catch block specific for catching the DummyException we can set a routine for what to do when that type of Exception is thrown. In this case, nothing. The example also shows that you can use multiple catch blocks. All that one does is catch any exception that is not a DummyException, because the script does not know the exact type of exception, or rather, the developer has not created a catch() block to accomodate for it, it prints the message and terminates the script.
A more complex example of try catch from one of the systems I've used in the past. (bit OTT for my liking but meh..):
Code: Select all
class DummyException extends Exception {}
class MyClass
{
public function __construct ()
{
throw new DummyException ('This is a dummy Exception!');
}
}
try {
$foo = new MyClass;
} catch (DummyException $e) {
echo 'DummyException caught.. continuing..';
} catch (Exception $e) {
echo 'Uknown Exception caught. Terminating Script.';
echo $e->getMessage();
die;
}A more complex example of try catch from one of the systems I've used in the past. (bit OTT for my liking but meh..):
Code: Select all
/*
* user login..
*/
try {
/*
* create User object
*/
$user = new User($db);
/*
* login
*/
$user->login($$METHOD['uname'], $$METHOD['pass']);
/*
* ConnectionException thrown when Database, or connection to Database, not available.
*/
} catch (ConnectionException $e) {
/* log the exception for investigation */
Error::logException($e);
/* raise incident for support */
Error::raiseIncident($e);
/* generate user friendly message */
Error::setMessage('There has been an error connecting to the Database.'
. 'An incident report has been raised. Please try again later.');
/* terminate */
Error::terminate();
/*
* AuthenticationException thrown when user credentials are incorrect/invalid.
*/
} catch (AuthenticationException $e) {
/* generate user friendly message */
Error::setMessage('Username and/or Password incorrect. Please try again.');
/* terminate */
Error::terminate();
/*
* UserProhibitedException thrown when user has been banned.
*/
} catch (UserProhibitedException $e) {
/* generate user frindly exception */
Error::setMessage('Sorry, that account has been banned. Please contact the administrator for further details.');
/* terminate */
Error::terminate();
/*
* Unknown Exception - log and set for highest priority.
*/
} catch (Exception $e) {
/* log the error for investigation */
Error::logException($e);
/* raise incident and set high priority */
Error::raiseIncident($e);
Error::setPriority(1);
/* generate user friendly message */
Error::setMessage('There has been an error.'
. 'An incident has been raised and will be investigated. Please try again later.');
/* terminate */
Error::terminate();
}- daedalus__
- DevNet Resident
- Posts: 1925
- Joined: Thu Feb 09, 2006 4:52 pm
- daedalus__
- DevNet Resident
- Posts: 1925
- Joined: Thu Feb 09, 2006 4:52 pm
Thoughts, opinions, questions, comments, praises, flames, and money all appreciated and accepted!
I fixed it up, and used that observer pattern, which I completely understand now, thanks everyone!
I realise that it lacks error handling of most or any kind but I will fix that later.
I want to try out this try...catch stuff but don't completely understand it yet..
EDIT: I realise there are problems with the ToLogFile class or whatever I called it, but at the end of a 20 hour day, I am too tired to finish it.
I fixed it up, and used that observer pattern, which I completely understand now, thanks everyone!
Code: Select all
<?php
class ErrorHandler
{
// Properties
private $observers = array();
// Constructor and Destructor (if needed)
public function __construct()
{
set_error_handler(array($this, 'CallObservers'));
}
// Load Observers
public function LoadObserver($object)
{
$this->observers[] =& $object;
}
// Unload Observers
public function UnloadObserver($id)
{
unset($this->observers[$id]);
}
// Call Observers
public function CallObservers($level, $message, $file, $line)
{
for ($i = 0; $i < $this->CountObservers(); $i++)
{
$this->observers[$i]->HandleError($level, $message, $file, $line, $this->CountObservers());
}
}
// Methods
private function CountObservers()
{
return count($this->observers);
}
}
class ErrorHandlerToBrowser
{
// Properties
private $friendly;
// Constructor
public function __construct($friendly)
{
$this->SetFriendlyErrors($friendly);
}
// Setters
private function SetFriendlyErrors($int)
{
if (is_int($int) != FALSE)
{
$this->friendly = (($int > 0) != FALSE) ? 1 : 0;
}
}
// Getters
private function GetFriendlyErrors()
{
if (isset($this->friendly))
{
return $this->friendly;
}
}
// Methods
public function HandleError($level, $message, $file, $line, $observers)
{
// First check to see if friendly messages are on.
if (1 == $this->GetFriendlyErrors())
{
print "We're sorry, an error has occured.<br />\n";
}
else
{
print "<pre>";
print "<b>$level</b>\n$message\n<i>$file</i> on line <b>$line</b>";
print "</pre>";
}
// Check to see if this is the only observer
if (1 == $observers)
{
print "This Error has <b>not</b> been logged, please report it to an administrator.";
}
else
{
print "This Error has been logged, you may refresh the page and re-try the operation, or you may go <a href=\"/\">back</a> to the home page.";
}
}
}
class ErrorHandlerToDatabase
{
// Properties
private $table;
// Constructor and Destructor
public function __construct($table)
{
$this->SetTableName($table);
}
// Setters
private function SetTableName($table)
{
if (is_string($table) != FALSE)
{
$this->table == $table;
}
}
// Getters
private function GetTableName()
{
return $this->table;
}
// Methods
public function HandleError($level, $message, $file, $line, $count = '')
{
$sql = sprintf("INSERT INTO %s (id, level, message, file, line)
VALUES (NULL, '%s', '%s', '%s', '%d')",
$this->GetTableName(), $level, $message, $file, $line);
mysql_query($sql);
if (mysql_affected_rows() > 0)
{
print "The error was logged into the database successfully!";
}
}
}
class ErrorHandlerToLog
{
// Properties
private $log_file_path;
private $log_file_name;
private $log_file_frequency; // This is how often to create a new log file.
// Daily, Weekly, Monthly, Yearly, Never
// Constructor
public function __construct($log_file_path, $log_file_name, $log_file_frequency)
{
$this->SetLogFrequency($log_file_frequency);
$this->SetLogPath($log_file_path);
$this->SetLogName($log_file_name);
}
// Setters
private function SetLogPath($log_file_path)
{
$this->log_file_path = $log_file_path;
if (substr($log_file_path, strlen($log_file_path)-1, 1) != '/')
{
$this->log_file_path .= '/';
}
}
private function SetLogName($log_file_name)
{
switch ($this->GetLogFrequency())
{
case 'daily':
$this->log_file_name = $log_file_name.date('\_M\_d\_Y');
break;
case 'weekly':
$this->log_file_name = $log_file_name.date('\_W\_Y');
break;
case 'monthly':
$this->log_file_name = $log_file_name.date('\_M\_Y');
break;
case 'yearly':
$this->log_file_name = $log_file_name.date('\_Y');
break;
default:
$this->log_file_name = $log_file_name;
break;
}
$this->log_file_name .= '.log';
}
private function SetLogFrequency($log_file_frequency)
{
$valid_args = array('daily', 'weekly', 'monthly', 'yearly', 0);
if (in_array($log_file_frequency, $args) != FALSE)
{
$this->log_file_frequency = $log_file_frequency;
}
}
// Getters
private function GetLogPath()
{
return $this->log_file_path;
}
private function GetLogName()
{
return $this->log_file_name;
}
private function GetLogFrequency()
{
return $this->log_file_frequency;
}
// Methods
public function HandleError($level, $message, $file, $line, $count = '')
{
$error_str = $level.', '.$message.', '.$file.', '.$line;
$file = fopen($this->GetLogPath().$this->GetLogName(), 'a') or die('could not open');
fwrite($file, $error_str);
fclose($file);
}
}
function __autoload($class_name)
{
include_once("inc/$class_name.class.php");
}
$ErrorHandler = new ErrorHandler();
$ErrorHandler->LoadObserver(new ErrorHandlerToBrowser(1));
getimagesize('bleat.jpg');I want to try out this try...catch stuff but don't completely understand it yet..
EDIT: I realise there are problems with the ToLogFile class or whatever I called it, but at the end of a 20 hour day, I am too tired to finish it.
Last edited by daedalus__ on Thu Jul 27, 2006 2:07 am, edited 1 time in total.
- daedalus__
- DevNet Resident
- Posts: 1925
- Joined: Thu Feb 09, 2006 4:52 pm
updated, look up
updated, look up