一直对框架的错误处理有些疑惑,为什么我的程序一旦出现问题,就会自动打印出错误呢?他是怎么监听的?在哪里用的try catch吗??
这是我一直以来的困惑,可现在知道了,原来,原来php有自己的API当
程序出现问题时,可以自动调用指定函数,进行处理
YII2启动的时候,会自动注册错误处理函数
set_error_handler
public function __construct($config = [])
{
Yii::$app = $this;
static::setInstance($this);
$this->state = self::STATE_BEGIN;
$this->preInit($config);
$this->registerErrorHandler($config);
Component::__construct($config);
}
对,就是这个registerErrorHandler,其定义如下:
protected function registerErrorHandler(&$config)
{
if (YII_ENABLE_ERROR_HANDLER) {
if (!isset($config['components']['errorHandler']['class'])) {
echo "Error: no errorHandler component is configured.\n";
exit(1);
}
$this->set('errorHandler', $config['components']['errorHandler']);
unset($config['components']['errorHandler']);
$this->getErrorHandler()->register();
}
}
在components中是这样定义的:
'errorHandler' => [
'errorAction' => 'site/error',
],
而site/error则是在siteController中的actions中定义的!!!
/**
* @inheritdoc
*/
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
这样,error的定义是在yii\web\errorAction当中,也就是说,我们需要看这个类的定义ErrorHandler
在启动的时候,调用了register,其定义如下:
public function register()
{
ini_set('display_errors', false);
set_exception_handler([$this, 'handleException']);
if (defined('HHVM_VERSION')) {
set_error_handler([$this, 'handleHhvmError']);
} else {
set_error_handler([$this, 'handleError']);
}
if ($this->memoryReserveSize > 0) {
$this->_memoryReserve = str_repeat('x', $this->memoryReserveSize);
}
register_shutdown_function([$this, 'handleFatalError']);
}
调用了handlerError成员函数
public function handleError($code, $message, $file, $line)
{
if (error_reporting() & $code) {
// load ErrorException manually here because autoloading them will not work
// when error occurs while autoloading a class
if (!class_exists('yii\\base\\ErrorException', false)) {
require_once(__DIR__ . '/ErrorException.php');
}
$exception = new ErrorException($message, $code, $code, $file, $line);
// in case error appeared in __toString method we can't throw any exception
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);//得到调用栈数组
array_shift($trace);
foreach ($trace as $frame) {
if ($frame['function'] === '__toString') {
$this->handleException($exception);
if (defined('HHVM_VERSION')) {
flush();
}
exit(1);
}
}
throw $exception;
}
return false;
}
这样我们就能得到完整的错误信息的调用情况了