Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.8k views
in Technique[技术] by (71.8m points)

为什么PDOException不能被set_error_handler、set_exception_handler所捕获

入口文件注册错误处理机制

// 设定报错级别为全部
error_reporting(E_ALL);
// 设定错误日志记录文件
ini_set('error_log',SYSTEM_LOGS_DIR.date("Ymd") . '_log.txt');
// 显示错误日志
ini_set('display_errors', '1');
// set_error_handler — 设置用户自定义的错误处理函数
set_error_handler([__CLASS__, 'appError']);
// set_exception_handler — 设置用户自定义的异常处理函数
set_exception_handler([__CLASS__, 'appException']);
// register_shutdown_function — 注册一个会在php中止时执行的函数,脚本执行完成或者 exit() 后被调用
register_shutdown_function([__CLASS__, 'appShutdown']);

但是当pdo insert的时候,如果我的字段过长
出现data too long for column的时候这两个函数都没有捕获到
只能通过到

try{
    $WorkListModelObj->insert($historyWork);
}catch(Throwable $e){
    // PDOException
    echo $e->getCode();
    echo $e->getMessage();
}

所捕获到,这是为啥,有时候数组 undefined index 的时候:

PHP Notice:  Undefined index: test -- 无法被try-catch捕获-会被set_error_handler所捕获

有时候

// a();// PHP Fatal error:  Uncaught Error: Call to undefined function a()  -- try-catch也不能捕获
// php由上到下解析的,如果前面已经注册了set_exception_handler,那么将会被捕获,注意必须是这一行前面,不能是后面

我凌乱了
如何才能实现一个完美捕获所有php错误和异常并进行自己处理的程序

附上:

<?php

/**
 * 
 * 错误处理机制
 * @author wystanxu <[email protected]>
 * @since 1.0.0
 * 
 */
class ErrorCatch
{
    /**
     * 注册异常处理
     * @access public
     * @return void
     */
    public static function register()
    {
        // 设定报错级别为全部
        error_reporting(E_ALL);
        // 设定错误日志记录文件
        ini_set('error_log', dirname(__DIR__) . '/' . date("Ymd") . '_log.txt');
        // 显示错误日志
        ini_set('display_errors', '1');
        // set_error_handler — 设置用户自定义的错误处理函数
        set_error_handler([__CLASS__, 'appError']);
        // set_exception_handler — 设置用户自定义的异常处理函数
        set_exception_handler([__CLASS__, 'appException']);
        // register_shutdown_function — 注册一个会在php中止时执行的函数,脚本执行完成或者 exit() 后被调用
        register_shutdown_function([__CLASS__, 'appShutdown']);
    }

    /**
     * 错误处理
     * @access public
     * @param  integer $errno      错误编号
     * @param  integer $errstr     详细错误信息
     * @param  string  $errfile    出错的文件
     * @param  integer $errline    出错行号
     * @param  array   $errcontext 出错上下文
     * @return void
     * @throws ErrorException
     */
    public static function appError($errno, $errstr, $errfile = '', $errline = 0, $errcontext = [])
    {
        echo "appErr";
        $msg = '错误编号:' . $errno . "

";
        $msg .= '错误信息:' . $errstr . "

";
        $msg .= '文件:' . $errfile . "

";
        $msg .= '在第:' . $errline . "行

";
        echo $msg;
        // 记录错误日志到文本
        error_log($msg, 3, ini_get("error_log"));
    }

    /**
     * 异常处理
     * @access public
     * @param   Exception $e 异常对象
     * @return void
     */
    public static function appException($exception)
    {
        $msg = "捕获异常: ".$exception->getMessage()."

";
        echo $msg;
        // 记录错误日志到文本
        error_log($msg, 3, ini_get("error_log"));
    }

    /**
     * 异常中止处理
     * @access public
     * @return void
     */
    public static function appShutdown()
    {
        // 只有错误导致的程序终止才会托管至错误处理函数
        if (!is_null($error = error_get_last()) && self::isFatal($error['type'])) {
            echo "appShutdown".PHP_EOL;
            self::appException(new ErrorException(
                $error['type'],
                $error['message'],
                $error['file'],
                $error['line']
            ));
        }
    }

    /**
     * 确定错误类型是否致命
     * @access protected
     * @param  int $type 错误类型
     * @return bool
     */
    protected static function isFatal($type)
    {
        return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE]);
    }
}

// 注册自定义错误处理
ErrorCatch::register();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

错误和异常级别不一样,有的错误和异常会直接终止脚本。

在 index.php 中引入另一个文件 controller.php , 在 index.php 捕获 controller.php 异常和错误,执行 index.php 。

这样的话就算 controller.php 抛出严重的错误和异常,导致 controller.php 脚本终止,但并不影响 index.php ,在 index.php 中可以正常捕获到异常。


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...