首页 > 编程 > PHP > 正文

PHP中的异常处理

2020-03-22 16:28:29
字体:
来源:转载
供稿:网友
  • 1.什么是异常?异常和错误有什么区别?

    1.异常:程序运行与预期不太一致,与错误是两个不同的概念!
    2.抛出和捕获异常
    3.多个catch块的时候基类要往后放,否则基类捕获异常后就不会往下继续捕获了!
    3.先出现错误,在出现异常,所以写api的时候一定要把display_errors关掉
    4.php的内置异常

    error_reporting(-1);ini_set('display_errors','off');//pdo内置异常类try {    $pdo = new PDO('mysql:host=localhost;dbname=mysql', 'brave', '123456');    var_dump($pdo);    echo '<hr/>';    echo 'continue.......';} catch (Exception $e) {    echo $e->getMessage();}echo 'this is a test.......';echo '<hr/>';//spl文件读写内置异常类try {    $splObj = new SplFileObject('test.txt', 'r');    echo 'read file';} catch (RuntimeException $e) {    echo $e->getMessage();}echo 'continue.......';echo '<hr/>';

    2.异常的基本语法结构
        try {        //需要进行异常处理的代码        throw语句抛出    } catch (PdoException $e) {        try {             throw语句抛出        } catch (Exception $e) {        }    } catch (FileException $e) {    } catch (CustomException $e) {    }    //other code

    3.如何自定义异常类?
    error_reporting(-1);ini_set('display_errors','off');html' target='_blank'>class MyException extends Exception{    function __construct($message, $code=0)    {        parent::__construct($message, $code);    }    public function __toString(){        $message = '<h4>出现异常了,信息如下</h4>';        $message .='<p>'.__CLASS__.' [{$this->code}]:{$this->message}</p>';        return $message;    }    public function test(){        echo 'this is a test';    }    public function stop(){        exit('script end..............<hr/>');    }    //自定义其他方法}try {    echo '出现异常了!';    throw new MyException('测试自定义异常!', 11);} catch (MyException $e) {    echo $e->getMessage();     echo '<hr/>';    echo $e;    echo '<hr/>';    $e->stop();    $e->test();}

    4.自定义文件异常类
    error_reporting(-1);ini_set('display_errors','off');class FileException extends Exception{    public function getDetails()    {        switch ($this->code) {            case 0:                return '没有提供文件!';                break;            case 1:                return '文件不存在!'.' trace'.$this->getTraceAsString().$this->getLine();                break;            case 2:                return '不是一个文件!'.' trace'.$this->getTraceAsString().$this->getLine();                break;            case 3:                return '文件不可写!';                break;            case 4:                return '非法文件的操作模式!';                break;            case 5:                return '数据写入失败!';                break;            case 6:                return '文件不能被关闭!';                break;            default:                return '非法!';                break;        }    }}class WriteData{    private $_message='';    private $_fp=null;    public function __construct($filename=null, $mode='w'){        $this->_message='文件:{$filename} 模式:{$mode}';        if (empty($filename)) {            throw new FileException($this->_message, 0);        }        if (!file_exists($filename)) {            throw new FileException($this->_message, 1);        }        if (!is_file($filename)) {            throw new FileException($this->_message, 2);        }        if (!is_writable($filename)) {            throw new FileException($this->_message, 3);        }        if (!in_array($mode, array('w', 'w+', 'a', 'a+'))) {            throw new FileException($this->_message, 4);        }        $this->_fp=fopen($filename, $mode);    }    /**     * [write 写数据]     * @param  [type] $data [description]     * @return [type]       [description]     */    public function write($data){        if (@!fwrite($this->_fp, $data.PHP_EOL)) {            throw new FileException($this->_message, 5);        }    }    /**     * [close 关闭文件句柄]     * @return [type] [description]     */    public function close(){        if ($this->_fp) {            if (@!fclose($this->_fp)) {                throw new FileException($this->_message, 6);                $this->_fp=null;            }        }    }    public function __destruct(){        $this->close();    }}try {    $fp = new WriteData('test.txt', 'w');    $fp->write('this is a test');    $fp->close();    echo '数据写入成功!';} catch (FileException $e) {    echo '出问题了:'.$e->getMessage().' 详细信息如下:'.$e->getDetails();}

    5.使用观察者模式处理异常
    定义观察(异常)的类, 可以在代码中动态的添加观察者
        /**     * 观察(异常)的类, 可以在代码中动态的添加观察者     */    class Observable_Exception extends Exception    {        public static $_observers=array();        public static function attach(Exception_Observer $observer){            self::$_observers[]=$observer;        }        public function __construct($message=null, $code=0){            parent::__construct($message, $code);            $this->notify();        }        public function notify(){            foreach (self::$_observers as $observer) {                $observer->update($this);            }        }    }

    2.定义异常观察者基类,用于规范每一个观察者

        /**     * 观察者基类,用于规范每一个观察者     */    interface Exception_Observer{        //强制指定必须是我们规定的观察类        public function update(Observable_Exception $e);    }

    3.定义日志观察者

        /**     * 定义日志观察者     */    class Logging_Exception_Observer implements Exception_Observer{        public $_filename='./log_exception.log';        public function __construct($filename=null){            if ($filename!==null && is_string($filename)) {                $this->_filename=$filename;            }        }        public function update(Observable_Exception $e){            $message='时间:'.date('Y-m-d H:i:s').PHP_EOL;            $message.='信息:'.$e->getMessage().PHP_EOL;            $message.='追踪信息:'.$e->getTraceAsString().PHP_EOL;            $message.='文件:'.$e->getFile().PHP_EOL;            $message.='行号:'.$e->getLine().PHP_EOL;            error_log($message, 3, $this->_filename);        }    }

    4.定义邮件观察者

        /**     * 定义邮件观察者     */    class Email_Exception_Observer implements Exception_Observer{        public $_email='732578448@qq.com';        public function __construct($email=null){            if ($email!==null && filter_var($email, FILTER_VALIDATE_EMAIL)) {                $this->_email=$email;            }        }        public function update(Observable_Exception $e){            $message='时间:'.date('Y-m-d H:i:s').PHP_EOL;            $message.='信息:'.$e->getMessage().PHP_EOL;            $message.='追踪信息:'.$e->getTraceAsString().PHP_EOL;            $message.='文件:'.$e->getFile().PHP_EOL;            $message.='行号:'.$e->getLine().PHP_EOL;            error_log($message, 1, $this->_email);        }    }

    5.执行测试

    error_reporting(-1);ini_set('display_errors','off');//引入观察异常的类require 'Observable_Exception.php';//引入观察者基类require 'Exception_Observer.php';//引入日志观察者require 'Logging_Exception_Observer.php';//引入邮件观察者require 'Email_Exception_Observer.php';Observable_Exception::attach(new Logging_Exception_Observer());//自定义地址记录错误异常Observable_Exception::attach(new Logging_Exception_Observer('/tmp/test11.log'));Observable_Exception::attach(new Email_Exception_Observer());//自定义邮件接收人记录错误异常Observable_Exception::attach(new Email_Exception_Observer('123456@qq.com'));class MyException extends Observable_Exception{    public function test(){        echo 'this is a test!';    }    public function test1(){        echo '我是 自定义的方法处理这个异常!';    }}try {    throw new MyException('出现异常了,记录一下下!');} catch (MyException $e) {    echo $e->getMessage();    echo '<hr/>';    $e->test();    echo '<hr/>';    $e->test1();}

    6.自定义异常处理器(set_exception_handler)?

    1.目的1处理所有未捕获的异常
    2.目的2处理所有我们为放到try catch中的异常

    3.自定义异常处理函数
    ini_set('display_errors','off');function exceptionHandler_1($e){  echo '自定义异常处理器1'.__FUNCTION__;  echo '异常信息:'.$e->getMessage();}function exceptionHandler_2($e){  echo '自定义异常处理器2'.__FUNCTION__;  echo '异常信息:'.$e->getMessage();}set_exception_handler('exceptionHandler_1');set_exception_handler('exceptionHandler_2');//恢复到上一次定义过的异常处理函数restore_exception_handler();throw new Exception('测试');echo 'continue........';echo '<hr/>';

    4.自定义异常处理类

    /** * 自定义错误异常类 */class ExceptionHandler{    protected $_exception;    protected $_logFile='./testExceptionHandler.log';    function __construct(Exception $e){        //保存异常对象        $this->_exception = $e;    }    public static function handle(Exception $e){        $self = new self($e);        $self->log();        echo $self;    }    public function log(){        $msg=<<<EOF        出现了通知错误,如下产生通知的文件:{$this->_exception->getFile()}<br>产生通知的信息:{$this->_exception->getTraceAsString()}产生通知的行号:{$this->_exception->getLine()}产生通知的错误号:{$this->_exception->getCode()}产生通知的时间:{$datetime}EOF;        echo $msg;        error_log($msg, 3, $this->_logFile);    }    public function __toString(){        $message = <<<EOF        <!DOCTYPE html>        <html>        <head>            <title></title>        </head>        <body>            <h3>出现异常了。。。。。</h3>            <p>刷新下试试</p>        </body>        </html>EOF;        return $message;    }}ini_set('display_errors','off');set_exception_handler(array('ExceptionHandler', 'handle'));//放在try catch中的throwtry {    throw new Exception('this is a test!',20010);} catch (Exception $e) {    echo $e->getMessage();}//没放在try catch中的throwthrow new Exception('测试未捕获的自定义的异常处理器hello world!',2008);

    7.如何像处理异常一样处理PHP的错误?

    1.通过ErrorException

    function exception_error_handler($errno, $errstr, $errfile, $errline){    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);}set_error_handler('exception_error_handler');try {    echo gettype();} catch (Exception $e) {    echo $e->getMessage();}

    2.自定义异常类

    class ErrorToException extends Exception{    public static function handle($errno, $errstr)    {        throw new self($errstr, $errno);    }}ini_set('display_errors', 'off');set_error_handler(array('ErrorToException', 'handle'));set_error_handler(array('ErrorToException', 'handle'),E_USER_WARNING|E_WARNING);try {    echo $test;    gettype();    trigger_error('test',E_USER_WARNING);} catch (Exception $e) {    echo $e->getMessage();}

    8.在发生错误的时候将用户重定向到另一个页面
    class ExceptionRedirectHandler{    protected $_exception;    protected $_logFile='./redirectLog.log';    protected $_redirect='404.html';    public function __construct(Exception $e){        $this->_exception=$e;    }    public static function handle(Exception $e){        $self = new self($e);        $self->log();        while (@ob_end_clean());        header('HTTP/1.1 307 Temporary Redirect');        header('Cache-Control:no-cache,must-revalidate');        header('Expires: Wed, 01 Jul 2015 07:40:45 GMT');        header('Location:'.$self->_redirect);        exit(1);    }    public function log($value=''){        error_log($this->_exception->getMessage().PHP_EOL, 3, $this->_logFile);    }}ini_set('display_errors','off');set_exception_handler(array('ExceptionRedirectHandler', 'handle'));$link = mysql_connect('localhost', 'brave', '123456123');if (!$link) {    throw new Exception('数据库受到攻击了,赶快去看看吧!');}

    9.设置自定义错误和异常需要传递的参数

    异常传递:$msg, $code
    错误传递:$errno, $errmsg, $errfile, $errline 可看MyErrorHandler.php

    PHP编程

    郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

  • 发表评论 共有条评论
    用户名: 密码:
    验证码: 匿名发表