CErrorHandler
优质
小牛编辑
134浏览
2023-12-01
所有包 | 属性 | 方法
CErrorHandler是用来处理未捕获的PHP错误和异常。
它根据应用程序的运行模式, 显示相应的错误。 它选择优先的语言显示错误。
CErrorHandler使用两种视图:
开发视图是当应用程序为调试模式时显示的视图 (即YII_DEBUG定义为true)。 这种视图显示了详细的错误信息和源代码。 生产视图是当应用程序为产品模式时显示给最终用户的视图。 出于安全原因,它们只显示了错误信息, 没有其它机密信息。
CErrorHandler按以下顺序查找视图模板:
maxSourceLines属性可以指定在开发视图中 显示的最大源代码行数。
CErrorHandler 是一个核心应用组件,它能随时通过 CApplication::getErrorHandler()访问。
源码: framework/base/CErrorHandler.php#392 (显示)
源码: framework/base/CErrorHandler.php#127 (显示)
源码: framework/base/CErrorHandler.php#288 (显示)
源码: framework/base/CErrorHandler.php#373 (显示)
源码: framework/base/CErrorHandler.php#327 (显示)
源码: framework/base/CErrorHandler.php#354 (显示)
源码: framework/base/CErrorHandler.php#93 (显示)
源码: framework/base/CErrorHandler.php#200 (显示)
源码: framework/base/CErrorHandler.php#136 (显示)
源码: framework/base/CErrorHandler.php#278 (显示)
源码: framework/base/CErrorHandler.php#447 (显示)
源码: framework/base/CErrorHandler.php#307 (显示)
源码: framework/base/CErrorHandler.php#464 (显示)
包 | 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使用两种视图:
- 开发视图,名为
exception.php
; - 生产视图,名为
error<StatusCode>.php
;
开发视图是当应用程序为调试模式时显示的视图 (即YII_DEBUG定义为true)。 这种视图显示了详细的错误信息和源代码。 生产视图是当应用程序为产品模式时显示给最终用户的视图。 出于安全原因,它们只显示了错误信息, 没有其它机密信息。
CErrorHandler按以下顺序查找视图模板:
themes/ThemeName/views/system
: when a theme is active.protected/views/system
framework/views
maxSourceLines属性可以指定在开发视图中 显示的最大源代码行数。
CErrorHandler 是一个核心应用组件,它能随时通过 CApplication::getErrorHandler()访问。
公共属性
隐藏继承属性
属性 | 类型 | 描述 | 定义在 |
---|---|---|---|
adminInfo | string | 应用程序管理员信息(可以是一个名字或电子邮件链接)。它会显示在最终用户的错误面页,默认为‘the webmaster’。 | CErrorHandler |
behaviors | array | 这个应用组件附加的行为。 这此行为将在应用组件调用init时附加在应用组件上。 请参照CModel::behaviors如何指定此属性值。 | CApplicationComponent |
discardOutput | boolean | 是否抛弃错误显示之前的输出内容,默认为true。 | CErrorHandler |
error | array | 返回当前正在处理的错误的详细信息。 | CErrorHandler |
errorAction | string | 被用来显示外部错误信息的控制其动作的路由(例如‘site/error’)。 在动作中,它通过Yii::app()->errorHandler->error得到相关的错误信息。 这个属性默认为null,意味着CErrorHandler将处理错误显示。 | CErrorHandler |
isInitialized | boolean | 检查应用组件是否已经初始化。 | CApplicationComponent |
maxSourceLines | integer | 显示最大源代码行数,默认25。 | CErrorHandler |
maxTraceSourceLines | integer | 显示最大跟踪源代码行数,默认10。 | CErrorHandler |
受保护属性
隐藏继承属性
属性 | 类型 | 描述 | 定义在 |
---|---|---|---|
versionInfo | string | 返回服务版本信息。 | 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 - 发生错误的上下文源码
被用来显示外部错误信息的控制其动作的路由(例如‘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) | ||
$args | array | 要转换的参数数组 |
{return} | string | 参数数组的字符串表现 |
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。 |
publicfunctiongetError()
{
return$this->_error;
}
返回当前正在处理的错误的详细信息。 该错误返回的数组包含如下信息:
- code - HTTP状态码(例如403‘500)
- type - 错误类型(例如‘CHttpException’,‘PHP Error’)
- message - 错误信息
- file - 发生错误的PHP脚本文件名
- line - 发生错误的代码行号
- trace - 错误的调用堆栈
- source - 发生错误的上下文源码
protected array getExactTrace(Exception $exception) | ||
$exception | Exception | 未捕获到的异常 |
{return} | array | 问题出现的详细跟踪信息 |
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 | 服务版本信息。生产模式将返回空字符串。 |
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) | ||
$view | string | 视图名(无论是‘exception’还是‘error’) |
$code | integer | HTTP状态码 |
{return} | string | 视图文件路径 |
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) | ||
$viewPath | string | 包含视图的目录 |
$view | string | 视图名(无论是‘exception’还是‘error’) |
$code | integer | HTTP状态码 |
$srcLanguage | string | 视图文件的语言 |
{return} | string | 视图文件的路径 |
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) | ||
$event | CEvent | 包含异常/错误信息的事件 |
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) | ||
$event | CErrorEvent | PHP错误事件 |
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) | ||
$exception | Exception | 捕获的异常 |
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请求。 |
protectedfunctionisAjaxRequest()
{
returnisset($_SERVER['HTTP_X_REQUESTED_WITH'])&&$_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
}
当前请求是否是一个AJAX(XMLHttpRequest)请求。
isCoreCode() 方法protected boolean isCoreCode(array $trace) | ||
$trace | array | 跟踪数据 |
{return} | boolean | 是否从应用程序代码中调用堆栈。 |
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) | ||
$view | string | 视图名(不带扩展名的文件名)。 参见getViewFile如何定位视图文件。 |
$data | array | 传递给视图的数据 |
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) | ||
$file | string | 源文件路径 |
$errorLine | integer | 错误行号 |
$maxLines | integer | 显示最大行数 |
{return} | string | 渲染结果 |
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>';
}
渲染围绕错误行源代码。