Home  >  Article  >  Backend Development  >  Errors and exceptions encountered by PHP programmers Part 2: Exceptions

Errors and exceptions encountered by PHP programmers Part 2: Exceptions

不言
不言Original
2018-04-14 15:02:111492browse

This article introduces the errors and exceptions encountered by PHP programmers. Now I share it with everyone. Friends in need can refer to it

Previous article:In those years, errors and exceptions encountered by PHP: Errors in the previous article

1. Introduction and use of exceptions in PHP

1.1 Exception execution process

try
{
    // 需要进行异常处理的代码段;
    throw 语句抛出异常;
}catch( Exception $e )
{
    ... 
}
catch( Exception $e )
{
    // 处理异常
}
contine.....

Not yet The caught exception will report a fatal error: Fatal error:Uncaught exception.....

1.2 PHP exception characteristics

  1. PHP will not actively catch exceptions. It needs to actively throw (throw) exceptions in the program to catch them.

  2. throwwill be automatically thrown upward

  3. throwThe statements after will not be executed

  4. try must be followed by catch, otherwise parse error Parse error

  5. ##
    try{
        $num1=3;
        $num2=0;
        if($num2==0){
            throw new Exception('0不能当作除数');
            echo 'this is a test';//看不到
        }else{
            $res=$num1/$num2;
        }
    }catch(Exception $e){
        echo $e->getMessage();
    }
1.3 PHP built-in exceptions

Php does not provide many exception classes like java, so many exceptions will be treated as errors. To change an error into an exception, you need to manually throwException object

PHP built-in exceptions such as: PDOException, SplFileObject Exceptions can be thrown automatically, and the subsequent code can continue to execute.

Errors and exceptions encountered by PHP programmers Part 2: Exceptions

Errors and exceptions encountered by PHP programmers Part 2: Exceptions##1.4 The difference between errors and exceptions

1.4.1 Exception handling

When an exception is thrown, the code after

throw will not continue to execute , PHP will try to find a matching catch block of code. If the exception is not caught and set_exception_handler() is not used for corresponding processing, then a serious error (Fatal Error) will occur and " Uncaught Exception" error message. 1.4.2 Basic syntax structure of exceptions

     

try - Code that requires exception handling should be placed in try within a code block to catch potential exceptions. If no exception is triggered, the code continues execution as usual. But if an exception is triggered, an exception will be thrown throw
- This specifies how to trigger the exception. Each try or throw must correspond to at least one catch. Use multiple catch code blocks to catch different kinds of exceptions.      catch
- catchThe code block will catch the exception and create an object containing the exception information1.4.3 Rethrow the exception

Sometimes, when an exception is thrown, you may want to handle it differently than the standard way. The exception can be thrown again in a

catch

block. Note that try{}catch{} is required to throw an exception again, and exceptions cannot be thrown directly in the catch code block. Scripts should hide system errors from users. System errors may be important to programmers, but users are not interested in them. To make it easier for users, you can throw the exception again with a user-friendly message.

In short: if an exception is thrown, you must catch it.


1.4.4 The difference between errors and exceptions

Exception: The program operation is not consistent with expectations
Error: The error is triggered

    When an error is encountered, the error itself is triggered and no exception is automatically thrown. Exceptions can be thrown through the
  • throw statement and caught through catch. If not caught, a fatal error will occur.

  • When an error occurs or is triggered, the script must be processed immediately. Exceptions can be passed up one by one until they are caught and then handled.
  • The error trigger does not have an associated code or name. Exceptions can be customized to handle error messages (the benefits of exceptions are reflected). They are thrown through code, captured and then processed
  • 2. Custom exception class

2.1 Custom exception class

    Custom exception class
  1. can only

    overwrite the constructor and toStringtwo functions

  2. Customized exception classes can add their own methods
  3. When there are multiple
  4. catch

    , generally Exceptionbase class At the end, The base class can call the method defined by the custom exception class

    /**
     * 自定义异常类
     * Class MyException
     */
    class MyException extends Exception
    {
        public function __construct($message = "", $code = 0, Throwable $previous = null)
        {
            parent::__construct($message, $code, $previous);
        }
        public function __toString()
        {
            $message = "<h2>出现异常了,信息如下</h2>";
            $message .= "<p>".__CLASS__."[{$this->code}]:{$this->message}</p>";
            return $message;
        }
        public function test()
        {
            echo &#39;this is a test&#39;;
        }
        public function stop()
        {
            exit(&#39;script end...&#39;);
        }
        //自定义其它方法
    }
    
    try{
        echo &#39;出现异常啦&#39;;
        throw new MyException(&#39;测试自定义异常&#39;);
    }catch (MyException $exception){
        echo $exception->getMessage();
        echo $exception;
    }
    //会继续执行
    echo &#39;continue.........&#39;;
    try{
        throw new MyException(&#39;测试自定义异常&#39;);
    }catch (Exception $exception){
        echo $exception->getMessage();
        $exception->test();
    } catch (MyException $exception){
        echo $exception->getMessage();
    }
  5. 2.2 Tips
//将错误用错误抑制符吸收,然后抛出异常
If(@!fwrite($filename,$data)) throw new exception(自定义异常)

PHP_EOL #换行符

How to record error log information:

     (1) :file_put_contents(LOG_PATH.'error.log';, '错误信息'.' '.date('Y-m-d H:i:s')."\r\n", FILE_APPEND);

     (2) :error_log('错误信息'.' '.date('Y-m-d H:i:s')."\r\n",3,LOG_PATH.'error.log');

2.3 使用观察者模式处理异常信息

Exception_Observer.php

/**
 * 给观察者定义规范
 *
 * Interface Exception_Observer
 */
interface Exception_Observer
{
    public function update(Observable_Exception $e);
}
Observable_Exception.php

/**
 * 定义观察者
 * Class Observable_Exception
 */
class Observable_Exception extends Exception
{
    //保存观察者信息
    public static $_observers = array();
    public static function attach(Exception_Observer $observer)
    {
        self::$_observers[] = $observer;
    }
    public function __construct($message = "", $code = 0, Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->notify();
    }
    public function notify()
    {
        foreach (self::$_observers as $observer) {
            $observer->update($this);
        }
    }
}
Logging_Exception_Observer.php

/**
 * 记录错误日志
 * Class Logging_Exception_Observer
 */
class Logging_Exception_Observer implements Exception_Observer
{
    protected $_filename = __DIR__.&#39;/error_observer.log&#39;;
    public function __construct($filename = null)
    {
        if ($filename!==null && is_string($filename)){
            $this->_filename = $filename;
        }
    }

    public function update(Observable_Exception $e)
    {
        $message = "时间:".date(&#39;Y:m:d H:i:s&#39;,time()).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);//写到日志中
    }
}
test.php

/**
 *测试
 */
header(&#39;content-type:text/html;charset=utf-8&#39;);
require_once &#39;Exception_Observer.php&#39;;
require_once &#39;Logging_Exception_Observer.php&#39;;
require_once &#39;Observable_Exception.php&#39;;

Observable_Exception::attach(new Logging_Exception_Observer());

class MyException extends Observable_Exception{
    public function test()
    {
        echo &#39;this is a test&#39;;
    }
}

try{
    throw new MyException(&#39;出现了异常!&#39;);
}catch (MyException $exception){
    echo $exception->getMessage();
}

三、自定义异常处理器

3.1 如何自定义异常处理器

3.1.1 自定义异常处理器

  1. 类似set_error_handler接管系统的错误处理函数,set_exception_handler接管所有没有被catch的异常

  2. restore_exception_handlerrestore_error_handler一样,本质上应该说从异常/错误处理函数栈中弹出一个。比如有一个异常处理函数,弹出一个的话,就没有异常处理函数,如果有异常没有捕获,会交由错误处理函数,如没有错误处理函数,异常最终会有系统错误处理函数处理。如果设置了2个异常处理函数,弹出一个,会交由下面一个异常处理函数处理。

/**
 * 自定义异常函数处理器
 */
header(&#39;content-type:text/html;charset=utf-8&#39;);
function exceptionHandler_1($e)
{
    echo &#39;自定义异常处理器1<br/>函数名:&#39;.__FUNCTION__.PHP_EOL;
    echo &#39;异常信息:&#39;.$e->getMessage();
}
function exceptionHandler_2($e)
{
    echo &#39;自定义异常处理器2<br/>函数名:&#39;.__FUNCTION__.PHP_EOL;
    echo &#39;异常信息:&#39;.$e->getMessage();
}

set_exception_handler(&#39;exceptionHandler_1&#39;);
//set_exception_handler(&#39;exceptionHandler_2&#39;);
//恢复到上一次定义过的异常处理函数,即exceptionHandler_1
//restore_exception_handler();
//致命错误信息
//restore_exception_handler();
throw new Exception(&#39;测试自定义异常处理器&#39;);

//自定义异常处理器,不会向下继续执行,因为throw之后不会再继续执行;try{} catch{}之后,会继续执行
//回顾:自定义错误处理器会继续执行代码,而手动抛出的错误信息不会继续执行
echo &#39;test&#39;;
/**
 * 自定义异常类处理器
 * Class ExceptionHandler
 */

class ExceptionHandler
{
    protected $_exception;
    protected $_logFile = __DIR__.&#39;/exception_handle.log&#39;;
    public function __construct(Exception $e)
    {
        $this->_exception = $e;
    }
    public static function handle(Exception $e)
    {
        $self = new self($e);
        $self->log();
        echo $self;
    }
    public function log()
    {
        error_log($this->_exception->getMessage().PHP_EOL,3,$this->_logFile);
    }

    /**
     * 魔术方法__toString()
     * 快速获取对象的字符串信息的便捷方式,直接输出对象引用时自动调用的方法。
     * @return string
     */
    public function __toString()
    {
        $message = <<<EOF
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Title</title>
        </head>
        <body>
            <h1>出现异常了啊啊啊啊</h1>
        </body>
        </html>
EOF;
    return $message;
    }

}
set_exception_handler(array(&#39;ExceptionHandler&#39;,&#39;handle&#39;));
/**
 * try catch不会被自定义异常处理!!!!
 */
try{
    throw new Exception(&#39;this is a test&#39;);
}catch (Exception $exception) {
    echo $exception->getMessage();
}
throw new Exception(&#39;测试自定义的异常处理器&#39;);

3.1.2 错误/异常之后是否继续执行代码问题总结

异常:

自定义异常处理器不会向下继续执行,因为throw之后不会再继续执行
try{} catch{}之后,会继续执行

错误:

自定义错误处理器会继续执行代码,而手动抛出的错误信息不会继续执行

3.2 像处理异常一样处理PHP错误

3.2.1 方式一:ErrorException

/**
 * 方式一:ErrorException错误异常类
 * @param $errno
 * @param $errstr
 * @param $errfile
 * @param $errline
 * @throws ErrorException
 */
function exception_error_handler($errno,$errstr,$errfile,$errline){

    throw new ErrorException($errstr,0,$errno,$errfile,$errline);
}

set_error_handler(&#39;exception_error_handler&#39;);

try{
    echo gettype();
}catch (Exception $exception){
    echo $exception->getMessage();
}

3.2.2 方式二:自定义异常类,继承基类Exception

/**
 * 方式二:自定义异常类
 * Class ErrorToException
 */
//显示所有的错误
error_reporting(-1);
class ErrorToException extends Exception{
    public static function handle($errno,$errstr)
    {
        throw new self($errstr,0);
    }
}

set_error_handler(array(&#39;ErrorToException&#39;,&#39;handle&#39;));
set_error_handler(array(&#39;ErrorToException&#39;,&#39;handle&#39;),E_USER_WARNING|E_WARNING);

try{
    echo $test;//notice,不会被处理
    echo gettype();//warning
    //手动触发错误
    trigger_error(&#39;test&#39;,E_USER_WARNING);
}catch (Exception $exception){
    echo $exception->getMessage();
}

3.3 PHP页面重定向实现

header(&#39;Content-type:text/html;charset=utf-8&#39;);
class ExceptionRedirectHandler{
    protected $_exception;
    protected $_logFile = __DIR__.&#39;redirect.log&#39;;
    public $redirect=&#39;404.html&#39;;
    public function __construct(Exception $e){
        $this->_exception=$e;
    }
    public static function handle(Exception $e){
        $self=new self($e);
        $self->log();
        // ob_end_clean()清除所有的输出缓冲,最后没有缓存的时候会产生通知级别的错误
        while(@ob_end_clean());
        header(&#39;HTTP/1.1 307 Temporary Redirect&#39;); //临时重定向
        header(&#39;Cache-Control:no-cache,must-revalidate&#39;);//no-cache强制向源服务器再次验证,must-revalidate可缓存但必须再向源服务器进行确认
        header(&#39;Expires: Sat, 28 Mar 2016 13:28:48 GMT&#39;); //资源失效的时间
        header(&#39;Location:&#39;.$self->redirect); //跳转
    }
    public function log(){
        error_log($this->_exception->getMessage().PHP_EOL,3,$this->_logFile);
    }
}
set_exception_handler(array(&#39;ExceptionRedirectHandler&#39;,&#39;handle&#39;));
$link=@mysqli_connect(&#39;127.0.0.1&#39;,&#39;root&#39;,&#39;1234561&#39;);
if(!$link){
    throw new Exception(&#39;数据库连接出错啦&#39;);
}

完!

参考课程视频:那些年你遇到的错误与异常

相关推荐:

PHP程序员遇到的错误与异常上篇之错误

The above is the detailed content of Errors and exceptions encountered by PHP programmers Part 2: Exceptions. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn