What I do, is have a class to create custom exceptions, but to standardise matters, I simply have one additional argument, which is an object (well, so far it's always been an array), which allows me to specify unlimited amount of exception data (much like a javascript exception).
Output:
Fatal error: Uncaught SqlProxyException 'Duplicate entry '1' for key 'PRIMARY'' in /usr/src/wrangler/trunk/common/SqlProxy.php(356)
#0 /usr/src/wrangler/trunk/common/SqlProxy.php(341): SqlProxy::Update('INSERT into tes...')
#1 /usr/src/wrangler/trunk/common/SqlProxy.php(455): SqlProxy::Insert('INSERT into tes...')
#2 {main}
Array
(
[sql] => INSERT into test SET test='1'
[errorObject] => Array
(
[status] => UNKNOWN
[data] => Array
(
[rowsAffected] => -1
[errorMsg] => Duplicate entry '1' for key 'PRIMARY'
[errorCode] => 1062
....
This is achieved by the following in my code:
<? require_once "CustomException.php";
## Define the custom exception
class SqlProxyException extends CustomException {}
## Throw a custom exception
throw new SqlProxyException($errorMsg, $errorCode, null,
array("sql" => $query, "errorObject" => $result)
);
## Catch the custom exception
try {
SqlProxy::Insert($argv[2]);
} catch (SqlProxyException $e) {
fprintf(STDERR, "Fatal error: Uncaught SqlProxyException '%s' in %s(%s)\n%s\n%s\n",
$e->getMessage(), $e->getFile(), $e->getLine(),
$e->getTraceAsString(),
$e->getObject() ? print_r($e->getObject(), 1) : ""
);
exit(1);
}
Not too difficult... and the magic behind CustomException.php is
<?php
interface IException
{
/* Protected methods inherited from Exception class */
public function getMessage(); // Exception message
public function getCode(); // User-defined Exception code
public function getFile(); // Source filename
public function getLine(); // Source line
public function getTrace(); // An array of the backtrace()
public function getTraceAsString(); // Formated string of trace
/* Overrideable methods inherited from Exception class */
public function __toString(); // formated string for display
public function __construct($message = null, $code = 0);
}
abstract class CustomException extends Exception implements IException
{
protected $message = 'Unknown exception'; // Exception message
private $string; // Unknown
protected $code = 0; // User-defined exception code
protected $file; // Source filename of exception
protected $line; // Source line of exception
protected $object = null; // Extra information in an object (array) js style
private $trace; // Unknown
public function __construct($message = null, $code = 0, Exception $previous = null, $eventObject = null)
{
if (!$message) {
throw new $this('Unknown '. get_class($this));
}
parent::__construct($message, $code, $previous);
$this->object = $eventObject;
}
public function __toString()
{
return get_class($this) . " '{$this->message}' in {$this->file}({$this->line})\n"
. "{$this->getTraceAsString()}";
}
/* Additional custom method */
public function getObject() // Return object (array) of extra info (js style)
{
return $this->object;
}
}