CErrorHandler

优质
小牛编辑
134浏览
2023-12-01
所有包 | 属性 | 方法
system.base
继承class CErrorHandler » CApplicationComponent » CComponent
实现IApplicationComponent
源自1.0
版本$Id: CErrorHandler.php 3540 2012-01-16 10:17:01Z mdomba $
源码framework/base/CErrorHandler.php
CErrorHandler是用来处理未捕获的PHP错误和异常。

它根据应用程序的运行模式, 显示相应的错误。 它选择优先的语言显示错误。

CErrorHandler使用两种视图:
  • 开发视图,名为exception.php;
  • 生产视图,名为error<StatusCode>.php;
<StatusCode>表示PHP错误代码(例如error500.php)。 本地化视图的命名是选择在本地语言的子目录下的代码 (例如,zh_cn/error500.php)。

开发视图是当应用程序为调试模式时显示的视图 (即YII_DEBUG定义为true)。 这种视图显示了详细的错误信息和源代码。 生产视图是当应用程序为产品模式时显示给最终用户的视图。 出于安全原因,它们只显示了错误信息, 没有其它机密信息。

CErrorHandler按以下顺序查找视图模板:
  1. themes/ThemeName/views/system: when a theme is active.
  2. protected/views/system
  3. framework/views
如果在目录下没有找到视图文件,它将在下一个目录查找。

maxSourceLines属性可以指定在开发视图中 显示的最大源代码行数。

CErrorHandler 是一个核心应用组件,它能随时通过 CApplication::getErrorHandler()访问。

公共属性

隐藏继承属性

属性类型描述定义在
adminInfostring应用程序管理员信息(可以是一个名字或电子邮件链接)。它会显示在最终用户的错误面页,默认为‘the webmaster’。CErrorHandler
behaviorsarray这个应用组件附加的行为。 这此行为将在应用组件调用init时附加在应用组件上。 请参照CModel::behaviors如何指定此属性值。CApplicationComponent
discardOutputboolean是否抛弃错误显示之前的输出内容,默认为true。CErrorHandler
errorarray返回当前正在处理的错误的详细信息。CErrorHandler
errorActionstring被用来显示外部错误信息的控制其动作的路由(例如‘site/error’)。 在动作中,它通过Yii::app()->errorHandler->error得到相关的错误信息。 这个属性默认为null,意味着CErrorHandler将处理错误显示。CErrorHandler
isInitializedboolean检查应用组件是否已经初始化。CApplicationComponent
maxSourceLinesinteger显示最大源代码行数,默认25。CErrorHandler
maxTraceSourceLinesinteger显示最大跟踪源代码行数,默认10。CErrorHandler

受保护属性

隐藏继承属性

属性类型描述定义在
versionInfostring返回服务版本信息。CErrorHandler

公共方法

隐藏继承方法

方法描述定义在
__call()如果类中没有调的方法名,则调用这个方法。CComponent
__get()返回一个属性值、一个事件处理程序列表或一个行为名称。CComponent
__isset()检查一个属性是否为null。CComponent
__set()设置一个组件的属性值。CComponent
__unset()设置一个组件的属性为null。CComponent
asa()返回这个名字的行为对象。CComponent
attachBehavior()附加一个行为到组件。CComponent
attachBehaviors()附加一个行为列表到组件。CComponent
attachEventHandler()为事件附加一个事件处理程序。CComponent
canGetProperty()确定属性是否可读。CComponent
canSetProperty()确定属性是否可写。CComponent
detachBehavior()从组件中分离一个行为。CComponent
detachBehaviors()从组件中分离所有行为。CComponent
detachEventHandler()分离一个存在的事件处理程序。CComponent
disableBehavior()禁用一个附加行为。CComponent
disableBehaviors()禁用组件附加的所有行为。CComponent
enableBehavior()启用一个附加行为。CComponent
enableBehaviors()启用组件附加的所有行为。CComponent
evaluateExpression()计算一个PHP表达式,或根据组件上下文执行回调。CComponent
getError()返回当前正在处理的错误的详细信息。CErrorHandler
getEventHandlers()返回一个事件的附加处理程序列表。CComponent
getIsInitialized()检查应用组件是否已经初始化。CApplicationComponent
handle()处理异常/错误事件。CErrorHandler
hasEvent()确定一个事件是否定义。CComponent
hasEventHandler()检查事件是否有附加的处理程序。CComponent
hasProperty()确定属性是否被定义。CComponent
init()初始化应用组件。CApplicationComponent
raiseEvent()发起一个事件。CComponent

受保护方法

隐藏继承方法

方法描述定义在
argumentsToString()转换参数数组为字符串表现。CErrorHandler
getExactTrace()返回问题发生的详细跟踪信息。CErrorHandler
getVersionInfo()返回服务版本信息。CErrorHandler
getViewFile()确定应该使用的视图文件。CErrorHandler
getViewFileInternal()查看指定目录下的视图。CErrorHandler
handleError()处理PHP错误。CErrorHandler
handleException()处理异常。CErrorHandler
isAjaxRequest()当前请求是否是一个AJAX(XMLHttpRequest)请求。CErrorHandler
isCoreCode()返回是否从应用程序代码中调用堆栈。CErrorHandler
render()渲染视图CErrorHandler
renderSourceCode()渲染围绕错误行源代码。CErrorHandler

属性详细

adminInfo 属性 public string $adminInfo;

应用程序管理员信息(可以是一个名字或电子邮件链接)。它会显示在最终用户的错误面页,默认为‘the webmaster’。

discardOutput 属性 public boolean $discardOutput;

是否抛弃错误显示之前的输出内容,默认为true。

error 属性 只读 public array getError()

返回当前正在处理的错误的详细信息。 该错误返回的数组包含如下信息:

  • code - HTTP状态码(例如403‘500)
  • type - 错误类型(例如‘CHttpException’,‘PHP Error’)
  • message - 错误信息
  • file - 发生错误的PHP脚本文件名
  • line - 发生错误的代码行号
  • trace - 错误的调用堆栈
  • source - 发生错误的上下文源码

errorAction 属性 public string $errorAction;

被用来显示外部错误信息的控制其动作的路由(例如‘site/error’)。 在动作中,它通过Yii::app()->errorHandler->error得到相关的错误信息。 这个属性默认为null,意味着CErrorHandler将处理错误显示。

maxSourceLines 属性 public integer $maxSourceLines;

显示最大源代码行数,默认25。

maxTraceSourceLines 属性 (可用自 v1.1.6) public integer $maxTraceSourceLines;

显示最大跟踪源代码行数,默认10。

versionInfo 属性 只读 protected string getVersionInfo()

返回服务版本信息。 如果应用是生产模式,将返回空字符串。

方法详细

argumentsToString() 方法
protected string argumentsToString(array $args)
$argsarray要转换的参数数组
{return}string参数数组的字符串表现
源码: framework/base/CErrorHandler.php#392 (显示) protectedfunctionargumentsToString($args)
{
$count=0;

$isAssoc=$args!==array_values($args);

foreach($argsas$key=>$value)
{
$count++;
if($count>=5)
{
if($count>5)
unset($args[$key]);
else
$args[$key]='...';
continue;
}

if(is_object($value))
$args[$key]=get_class($value);
elseif(is_bool($value))
$args[$key]=$value?'true':'false';
elseif(is_string($value))
{
if(strlen($value)>64)
$args[$key]='"'.substr($value,0,64).'..."';
else
$args[$key]='"'.$value.'"';
}
elseif(is_array($value))
$args[$key]='array('.$this->argumentsToString($value).')';
elseif($value===null)
$args[$key]='null';
elseif(is_resource($value))
$args[$key]='resource';

if(is_string($key))
{
$args[$key]='"'.$key.'"=>'.$args[$key];
}
elseif($isAssoc)
{
$args[$key]=$key.'=>'.$args[$key];
}
}
$out=implode(",",$args);

return$out;
}

转换参数数组为字符串表现。

getError() 方法
public array getError()
{return}array错误详细信息,如果没有错误返回null。
源码: framework/base/CErrorHandler.php#127 (显示) publicfunctiongetError()
{
return$this->_error;
}

返回当前正在处理的错误的详细信息。 该错误返回的数组包含如下信息:

  • code - HTTP状态码(例如403‘500)
  • type - 错误类型(例如‘CHttpException’,‘PHP Error’)
  • message - 错误信息
  • file - 发生错误的PHP脚本文件名
  • line - 发生错误的代码行号
  • trace - 错误的调用堆栈
  • source - 发生错误的上下文源码

getExactTrace() 方法
protected array getExactTrace(Exception $exception)
$exceptionException未捕获到的异常
{return}array问题出现的详细跟踪信息
源码: framework/base/CErrorHandler.php#288 (显示) protectedfunctiongetExactTrace($exception)
{
$traces=$exception->getTrace();

foreach($tracesas$trace)
{
//propertyaccessexception
if(isset($trace['function'])&&($trace['function']==='__get'||$trace['function']==='__set'))
return$trace;
}
returnnull;
}

返回问题发生的详细跟踪信息。

getVersionInfo() 方法
protected string getVersionInfo()
{return}string服务版本信息。生产模式将返回空字符串。
源码: framework/base/CErrorHandler.php#373 (显示) protectedfunctiongetVersionInfo()
{
if(YII_DEBUG)
{
$version='<ahref="http://www.yiiframework.com/">YiiFramework</a>/'.Yii::getVersion();
if(isset($_SERVER['SERVER_SOFTWARE']))
$version=$_SERVER['SERVER_SOFTWARE'].''.$version;
}
else
$version='';
return$version;
}

返回服务版本信息。 如果应用是生产模式,将返回空字符串。

getViewFile() 方法
protected string getViewFile(string $view, integer $code)
$viewstring视图名(无论是‘exception’还是‘error’)
$codeintegerHTTP状态码
{return}string视图文件路径
源码: framework/base/CErrorHandler.php#327 (显示) protectedfunctiongetViewFile($view,$code)
{
$viewPaths=array(
Yii::app()->getTheme()===null?null:Yii::app()->getTheme()->getSystemViewPath(),
Yii::app()instanceofCWebApplication?Yii::app()->getSystemViewPath():null,
YII_PATH.DIRECTORY_SEPARATOR.'views',
);

foreach($viewPathsas$i=>$viewPath)
{
if($viewPath!==null)
{
$viewFile=$this->getViewFileInternal($viewPath,$view,$code,$i===2?'en_us':null);
if(is_file($viewFile))
return$viewFile;
}
}
}

确定应该使用的视图文件。

getViewFileInternal() 方法
protected string getViewFileInternal(string $viewPath, string $view, integer $code, string $srcLanguage=NULL)
$viewPathstring包含视图的目录
$viewstring视图名(无论是‘exception’还是‘error’)
$codeintegerHTTP状态码
$srcLanguagestring视图文件的语言
{return}string视图文件的路径
源码: framework/base/CErrorHandler.php#354 (显示) protectedfunctiongetViewFileInternal($viewPath,$view,$code,$srcLanguage=null)
{
$app=Yii::app();
if($view==='error')
{
$viewFile=$app->findLocalizedFile($viewPath.DIRECTORY_SEPARATOR."error{$code}.php",$srcLanguage);
if(!is_file($viewFile))
$viewFile=$app->findLocalizedFile($viewPath.DIRECTORY_SEPARATOR.'error.php',$srcLanguage);
}
else
$viewFile=$viewPath.DIRECTORY_SEPARATOR."exception.php";
return$viewFile;
}

查看指定目录下的视图。

handle() 方法
public void handle(CEvent $event)
$eventCEvent包含异常/错误信息的事件
源码: framework/base/CErrorHandler.php#93 (显示) publicfunctionhandle($event)
{
//seteventashandledtopreventitfrombeinghandledbyothereventhandlers
$event->handled=true;

if($this->discardOutput)
{
//thefollowingmanuallevelcountingistodealwithzlib.output_compressionsettoOn
for($level=ob_get_level();$level>0;--$level)
{
@ob_end_clean();
}
}

if($eventinstanceofCExceptionEvent)
$this->handleException($event->exception);
else//CErrorEvent
$this->handleError($event);
}

处理异常/错误事件。 当捕获到异常或PHP错误时 调用此方法。

handleError() 方法
protected void handleError(CErrorEvent $event)
$eventCErrorEventPHP错误事件
源码: framework/base/CErrorHandler.php#200 (显示) protectedfunctionhandleError($event)
{
$trace=debug_backtrace();
//skipthefirst3stacksastheydonottelltheerrorposition
if(count($trace)>3)
$trace=array_slice($trace,3);
$traceString='';
foreach($traceas$i=>$t)
{
if(!isset($t['file']))
$trace[$i]['file']='unknown';

if(!isset($t['line']))
$trace[$i]['line']=0;

if(!isset($t['function']))
$trace[$i]['function']='unknown';

$traceString.="#$i{$trace[$i]['file']}({$trace[$i]['line']}):";
if(isset($t['object'])&&is_object($t['object']))
$traceString.=get_class($t['object']).'->';
$traceString.="{$trace[$i]['function']}()n";

unset($trace[$i]['object']);
}

$app=Yii::app();
if($appinstanceofCWebApplication)
{
switch($event->code)
{
caseE_WARNING:
$type='PHPwarning';
break;
caseE_NOTICE:
$type='PHPnotice';
break;
caseE_USER_ERROR:
$type='Usererror';
break;
caseE_USER_WARNING:
$type='Userwarning';
break;
caseE_USER_NOTICE:
$type='Usernotice';
break;
caseE_RECOVERABLE_ERROR:
$type='Recoverableerror';
break;
default:
$type='PHPerror';
}
$this->_error=$data=array(
'code'=>500,
'type'=>$type,
'message'=>$event->message,
'file'=>$event->file,
'line'=>$event->line,
'trace'=>$traceString,
'traces'=>$trace,
);
if(!headers_sent())
header("HTTP/1.0500PHPError");
if($this->isAjaxRequest())
$app->displayError($event->code,$event->message,$event->file,$event->line);
elseif(YII_DEBUG)
$this->render('exception',$data);
else
$this->render('error',$data);
}
else
$app->displayError($event->code,$event->message,$event->file,$event->line);
}

处理PHP错误。

handleException() 方法
protected void handleException(Exception $exception)
$exceptionException捕获的异常
源码: framework/base/CErrorHandler.php#136 (显示) protectedfunctionhandleException($exception)
{
$app=Yii::app();
if($appinstanceofCWebApplication)
{
if(($trace=$this->getExactTrace($exception))===null)
{
$fileName=$exception->getFile();
$errorLine=$exception->getLine();
}
else
{
$fileName=$trace['file'];
$errorLine=$trace['line'];
}

$trace=$exception->getTrace();

foreach($traceas$i=>$t)
{
if(!isset($t['file']))
$trace[$i]['file']='unknown';

if(!isset($t['line']))
$trace[$i]['line']=0;

if(!isset($t['function']))
$trace[$i]['function']='unknown';

unset($trace[$i]['object']);
}

$this->_error=$data=array(
'code'=>($exceptioninstanceofCHttpException)?$exception->statusCode:500,
'type'=>get_class($exception),
'errorCode'=>$exception->getCode(),
'message'=>$exception->getMessage(),
'file'=>$fileName,
'line'=>$errorLine,
'trace'=>$exception->getTraceAsString(),
'traces'=>$trace,
);

if(!headers_sent())
header("HTTP/1.0{$data['code']}".get_class($exception));

if($exceptioninstanceofCHttpException||!YII_DEBUG)
$this->render('error',$data);
else
{
if($this->isAjaxRequest())
$app->displayException($exception);
else
$this->render('exception',$data);
}
}
else
$app->displayException($exception);
}

处理异常。

isAjaxRequest() 方法
protected boolean isAjaxRequest()
{return}boolean当前请求是否是AJAX请求。
源码: framework/base/CErrorHandler.php#278 (显示) protectedfunctionisAjaxRequest()
{
returnisset($_SERVER['HTTP_X_REQUESTED_WITH'])&&$_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
}

当前请求是否是一个AJAX(XMLHttpRequest)请求。

isCoreCode() 方法
protected boolean isCoreCode(array $trace)
$tracearray跟踪数据
{return}boolean是否从应用程序代码中调用堆栈。
源码: framework/base/CErrorHandler.php#447 (显示) protectedfunctionisCoreCode($trace)
{
if(isset($trace['file']))
{
$systemPath=realpath(dirname(__FILE__).'/..');
return$trace['file']==='unknown'||strpos(realpath($trace['file']),$systemPath.DIRECTORY_SEPARATOR)===0;
}
returnfalse;
}

返回是否从应用程序代码中调用堆栈。

render() 方法
protected void render(string $view, array $data)
$viewstring视图名(不带扩展名的文件名)。 参见getViewFile如何定位视图文件。
$dataarray传递给视图的数据
源码: framework/base/CErrorHandler.php#307 (显示) protectedfunctionrender($view,$data)
{
if($view==='error'&&$this->errorAction!==null)
Yii::app()->runController($this->errorAction);
else
{
//additionalinformationtobepassedtoview
$data['version']=$this->getVersionInfo();
$data['time']=time();
$data['admin']=$this->adminInfo;
include($this->getViewFile($view,$data['code']));
}
}

渲染视图

renderSourceCode() 方法
protected string renderSourceCode(string $file, integer $errorLine, integer $maxLines)
$filestring源文件路径
$errorLineinteger错误行号
$maxLinesinteger显示最大行数
{return}string渲染结果
源码: framework/base/CErrorHandler.php#464 (显示) protectedfunctionrenderSourceCode($file,$errorLine,$maxLines)
{
$errorLine--;//adjustlinenumberto0-basedfrom1-based
if($errorLine<0||($lines=@file($file))===false||($lineCount=count($lines))<=$errorLine)
return'';

$halfLines=(int)($maxLines/2);
$beginLine=$errorLine-$halfLines>0?$errorLine-$halfLines:0;
$endLine=$errorLine+$halfLines<$lineCount?$errorLine+$halfLines:$lineCount-1;
$lineNumberWidth=strlen($endLine+1);

$output='';
for($i=$beginLine;$i<=$endLine;++$i)
{
$isErrorLine=$i===$errorLine;
$code=sprintf("<spanclass="ln".($isErrorLine?'error-ln':'')."">%0{$lineNumberWidth}d</span>%s",$i+1,CHtml::encode(str_replace("t",'',$lines[$i])));
if(!$isErrorLine)
$output.=$code;
else
$output.='<spanclass="error">'.$code.'</span>';
}
return'<divclass="code"><pre>'.$output.'</pre></div>';
}

渲染围绕错误行源代码。