> 백엔드 개발 > PHP 튜토리얼 > PHP 프로그래머가 직면한 오류 및 예외 2부: 예외

PHP 프로그래머가 직면한 오류 및 예외 2부: 예외

不言
풀어 주다: 2023-03-23 20:36:02
원래의
1565명이 탐색했습니다.

이 글은 PHP 프로그래머들이 겪었던 오류와 예외 사항을 소개합니다. 이제 여러분과 공유합니다. 도움이 필요한 친구들이 참고할 수 있습니다

이전 글: 그 시절 PHP에서 발생한 오류 그리고 예외: 이전 글의 오류

1. PHP에서 예외 소개 및 사용

1.1 예외 실행 프로세스

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

포착되지 않은 예외는 치명적인 오류를 보고합니다: 치명적인 오류: 포착되지 않은 예외.... Fatal error:Uncaught exception.....

1.2 PHP异常特点

  1. PHP不会主动捕获异常,需要程序中主动抛出 (throw)异常,才能捕获。

  2. throw会自动向上抛出

  3. throw之后的语句不会执行

  4. try后必须有catch,否则解析错误Parse error

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内置异常

Php不像java提供了很多异常类,所以很多异常都会当成错误。要想变错误为抛出异常,需要手动throw异常对象

PHP内置异常如:PDOExceptionSplFileObject 可以自动抛出异常,后面的代码可以继续执行。

PHP 프로그래머가 직면한 오류 및 예외 2부: 예외

PHP 프로그래머가 직면한 오류 및 예외 2부: 예외

1.4 错误和异常的区别

1.4.1 异常处理

当异常被抛出,throw后的代码不会继续执行PHP 会尝试查找匹配的 catch 代码块。如果异常没有被捕获,而且又没用使用set_exception_handler() 作相应的处理的话,那么将发生一个严重的错误(致命错误),并且输出 “Uncaught Exception” (未捕获异常)的错误消息。

1.4.2 异常的基本语法结构

try - 需要进行异常处理的代码应该放入try代码块内,以便捕获潜在的异常。如果没有触发异常,则代码将照常继续执行。但是如果异常被触发,会抛出一个异常
throw - 这里规定如何触发异常。每一个trythrow 必须对应至少一个 catch。使用多个catch代码块可以捕获不同种类的异常。
catch - catch代码块会捕获异常,并创建一个包含异常信息的对象

1.4.3 重新抛出异常

有时,当异常被抛出时,也许希望以不同于标准的方式对它进行处理。可以在一个 catch 代码块中再次抛出异常。注意再次抛出异常需要try{}catch{},不能直接在catch代码块中throw异常

脚本应该对用户隐藏系统错误。对程序员来说,系统错误也许很重要,但是用户对它们并不感兴趣。为了让用户更容易使用,您可以再次抛出带有对用户比较友好的消息的异常。
简而言之:如果抛出了异常,就必须捕获它。

1.4.4 错误与异常的区别

异常:程序运行与预期不太一致

错误:触发的是本身的错误

  • 当遇到错误的时候,触发的是本身的错误,不会自动的抛出异常。异常可以通过throw语句抛出异常,通过catch捕获异常,如果未捕获会产生致命错误。

  • 错误在发生的时候或触发的时候,必须马上对脚本进行处理。异常可以一一向上传递,直到被捕获,再处理。

  • 错误触发不具有相关代码或名称。异常可以自定义处理错误信息(异常的好处就体现出来了),是通过代码来抛出,捕获然后处理

二、自定义异常类

2.1 自定义异常类

  1. 自定义异常类只能重写构造函数和toString两个函数

  2. 自定义异常类可以增加自己的方法

  3. 多个catch 时,一般Exception1.2 PHP 예외 기능

    1. PHP
    2. 는 예외를 적극적으로 포착하지 않으며
    프로그램에서 적극적으로 처리해야 합니다( throw ) 예외가 포착될 수 있습니다.

  4. throw는 자동으로 위쪽으로 던집니다.

    🎜
  5. 🎜throw 이후의 명령문은 실행되지 않습니다🎜🎜
  6. 🎜try< /code> 뒤에는 <code>catch가 와야 합니다. 그렇지 않으면 구문 분석 오류 구문 분석 오류🎜🎜🎜
    /**
     * 自定义异常类
     * 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;;
    로그인 후 복사
    🎜1.3 PHP 내장 예외🎜🎜Php는 다음과 같습니다. java는 많은 예외 클래스를 제공하므로 많은 예외가 오류로 간주됩니다. 오류를 예외로 변경하려면 예외 객체 🎜🎜🎜PHP 내장 예외(예: 🎜PDOException, SplFileObject</)를 수동으로 <code>throw해야 합니다. code> 🎜자동으로 예외가 발생하고 다음 코드가 계속 실행될 수 있습니다. 🎜🎜🎜PHP 프로그래머가 직면한 오류 및 예외 2부: 예외 🎜🎜PHP 프로그래머가 직면한 오류 및 예외 2부: 예외🎜 🎜1.4 오류와 예외의 차이점🎜🎜1.4.1 예외 처리🎜🎜 예외가 발생하면 🎜throw🎜🎜 이후의 코드는 계속 실행되지 않습니다🎜, PHP</ code> 일치하는 <code>catch 블록을 찾으려고 시도합니다. 예외가 catch되지 않고 해당 처리에 set_Exception_handler()를 사용할 필요가 없으면 심각한 오류(🎜fatal error🎜)가 발생하고 "Uncaught Exception이 발생합니다. "(잡히지 않은 예외) 오류 메시지. 🎜🎜1.4.2 예외의 기본 구문 구조🎜🎜​​​ 🎜try🎜 - 예외를 처리해야 하는 코드는 잠재적인 가능성을 포착하기 위해 try 코드 블록 내에 배치되어야 합니다. 예외. 예외가 트리거되지 않으면 코드는 평소대로 계속 실행됩니다. 그러나 예외가 트리거되면 예외가 발생합니다.
    throw - 예외를 트리거하는 방법을 지정합니다. 각각의 🎜try🎜 또는 🎜throw🎜 🎜는 반드시🎜가 하나 이상의 🎜catch🎜와 일치해야 합니다. 여러 🎜catch🎜 블록을 사용하여 다양한 종류의 예외를 포착할 수 있습니다.
     catch - 🎜catch🎜코드 블록은 예외를 포착하고 예외 정보가 포함된 객체를 생성합니다🎜🎜1.4.3 예외 다시 발생🎜🎜 가끔 예외가 발생하면 어쩌면 표준과 다르게 취급하고 싶습니다. 🎜catch🎜 블록에서 예외가 다시 발생할 수 있습니다. 예외를 다시 발생시키려면 try{}catch{}가 필요하며 catch 코드 블록에서는 예외를 직접 발생시킬 수 없습니다. 🎜🎜 스크립트는 사용자에게 시스템 오류를 숨겨야 합니다. 시스템 오류는 프로그래머에게 중요할 수 있지만 사용자는 이에 관심이 없습니다. 사용자가 더 쉽게 사용할 수 있도록 사용자에게 친숙한 메시지를 사용하여 예외를 다시 발생시킬 수 있습니다.
    간단히 말해서, 예외가 발생하면 이를 잡아야 합니다. 🎜🎜1.4.4 오류와 예외의 차이점🎜
    예외: 프로그램 작동이 기대와 일치하지 않습니다.🎜오류: 오류가 저절로 발생합니다🎜
    • 🎜오류가 발생하면 오류 자체가 트리거되고 자동으로 예외가 발생하지 않습니다. 예외는 🎜throw🎜 문을 통해 발생하고 🎜catch🎜를 통해 포착될 수 있습니다. 그렇지 않으면 치명적인 오류가 발생합니다. 🎜🎜
    • 🎜오류가 발생하거나 트리거되면 즉시 스크립트를 처리해야 합니다. 예외는 발견되어 처리될 때까지 하나씩 전달될 수 있습니다. 🎜🎜
    • 🎜오류 트리거에는 관련 코드나 이름이 없습니다. 오류 메시지를 처리하기 위해 예외를 사용자 정의할 수 있습니다(예외의 이점이 반영됨). 예외는 코드를 통해 발생하고 캡처된 후 처리됩니다🎜🎜
    🎜 2. 사용자 정의 예외 클래스🎜🎜2.1 사용자 정의 예외 클래스🎜
    1. 🎜사용자 정의 예외 클래스🎜는🎜생성자와 toString 두 함수만 재정의할 수 있습니다🎜🎜
    2. 🎜사용자 정의 예외 클래스를 추가할 수 있습니다. 나만의 메서드 🎜🎜
    3. 🎜catch가 여러 개인 경우 Exception 기본 클래스는 일반적으로 끝에 배치됩니다. 🎜기본 클래스는 사용자 정의 예외 클래스에서 정의한 메서드를 호출할 수 있습니다🎜 🎜 🎜🎜
      try{
          throw new MyException(&#39;测试自定义异常&#39;);
      }catch (Exception $exception){
          echo $exception->getMessage();
          $exception->test();
      } catch (MyException $exception){
          echo $exception->getMessage();
      }
      로그인 후 복사
      //将错误用错误抑制符吸收,然后抛出异常
      If(@!fwrite($filename,$data)) throw new exception(自定义异常)
      
      PHP_EOL #换行符
      로그인 후 복사
      🎜2.2 팁🎜
      Exception_Observer.php
      
      /**
       * 给观察者定义规范
       *
       * Interface Exception_Observer
       */
      interface Exception_Observer
      {
          public function update(Observable_Exception $e);
      }
      로그인 후 복사
      로그인 후 복사
      🎜 오류 로그 정보를 기록하는 방법:🎜

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

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

      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程序员遇到的错误与异常上篇之错误

      위 내용은 PHP 프로그래머가 직면한 오류 및 예외 2부: 예외의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿