refactored error handling for better architecture.

This commit is contained in:
Taylor Otwell
2011-08-16 12:26:52 -05:00
parent e2c69d0c84
commit 5c3c2e2d9c
5 changed files with 259 additions and 126 deletions

View File

@@ -0,0 +1,117 @@
<?php namespace System\Exception;
use System\View;
use System\Config;
use System\Response;
class Handler {
/**
* The exception wrapper for the exception being handled.
*
* @var Wrapper
*/
public $exception;
/**
* Create a new exception handler instance.
*
* @param Exception $e
* @return void
*/
public function __construct($e)
{
$this->exception = new Wrapper($e);
}
/**
* Create a new exception handler instance.
*
* @param Exception $e
* @return Handler
*/
public static function make($e)
{
return new static($e);
}
/**
* Handle the exception and display the error report.
*
* The exception will be logged if error logging is enabled.
*
* The output buffer will be cleaned so nothing is sent to the browser except the
* error message. This prevents any views that have already been rendered from
* being shown in an incomplete or erroneous state.
*
* After the exception is displayed, the request will be halted.
*
* @return void
*/
public function handle()
{
if (ob_get_level() > 0) ob_clean();
if (Config::get('error.log')) $this->log();
$this->get_response(Config::get('error.detail'))->send();
exit(1);
}
/**
* Log the exception using the logger closure specified in the error configuration.
*
* @return void
*/
private function log()
{
$parameters = array(
$this->exception->severity(),
$this->exception->message(),
$this->exception->getTraceAsString(),
);
call_user_func_array(Config::get('error.logger'), $parameters);
}
/**
* Get the error report response for the exception.
*
* @param bool $detailed
* @return Resposne
*/
private function get_response($detailed)
{
return ($detailed) ? $this->detailed_response() : $this->generic_response();
}
/**
* Get the detailed error report for the exception.
*
* @return Response
*/
private function detailed_response()
{
$data = array(
'severity' => $this->exception->severity(),
'message' => $this->exception->message(),
'line' => $this->exception->getLine(),
'trace' => $this->exception->getTraceAsString(),
'contexts' => $this->exception->context(),
);
return Response::make(View::make('error.exception', $data), 500);
}
/**
* Get the generic error report for the exception.
*
* @return Response
*/
private function generic_response()
{
return Response::error('500');
}
}

View File

@@ -0,0 +1,110 @@
<?php namespace System\Exception;
use System\File;
class Wrapper {
/**
* The exception being wrapped.
*
* @var Exception
*/
public $exception;
/**
* Human-readable error levels and descriptions.
*
* @var array
*/
private $levels = array(
0 => 'Error',
E_ERROR => 'Error',
E_WARNING => 'Warning',
E_PARSE => 'Parsing Error',
E_NOTICE => 'Notice',
E_CORE_ERROR => 'Core Error',
E_CORE_WARNING => 'Core Warning',
E_COMPILE_ERROR => 'Compile Error',
E_COMPILE_WARNING => 'Compile Warning',
E_USER_ERROR => 'User Error',
E_USER_WARNING => 'User Warning',
E_USER_NOTICE => 'User Notice',
E_STRICT => 'Runtime Notice'
);
/**
* Create a new exception wrapper instance.
*
* @param Exception $e
* @return void
*/
public function __construct($e)
{
$this->exception = $e;
}
/**
* Get a human-readable version of the exception error code.
*
* @return string
*/
public function severity()
{
if (array_key_exists($this->exception->getCode(), $this->levels))
{
return $this->levels[$this->exception->getCode()];
}
return $this->exception->getCode();
}
/**
* Get the exception error message formatted for use by Laravel.
*
* The exception file paths will be shortened, and the file name and line number
* will be added to the exception message.
*
* @return string
*/
public function message()
{
$file = str_replace(array(APP_PATH, SYS_PATH), array('APP_PATH/', 'SYS_PATH/'), $this->exception->getFile());
return rtrim($this->exception->getMessage(), '.').' in '.$file.' on line '.$this->exception->getLine().'.';
}
/**
* Get the code surrounding the line where the exception occurred.
*
* @return array
*/
public function context()
{
return File::snapshot($this->exception->getFile(), $this->exception->getLine());
}
/**
* Magic Method to handle getting properties from the exception.
*/
public function __get($key)
{
return $this->exception->$key;
}
/**
* Magic Method to handle setting properties on the exception.
*/
public function __set($key, $value)
{
$this->exception->$key = $value;
}
/**
* Magic Method to pass function calls to the exception.
*/
public function __call($method, $parameters)
{
return call_user_func_array(array($this->exception, $method), $parameters);
}
}