zoukankan      html  css  js  c++  java
  • PHP学习(9)——错误和异常处理

    1.Exception类

      这个类是PHP为异常处理提供的内置类。构造函数的两个参数分别是错误消息和错误代码。

      除了构造函数之外,该类还提供了如下的内置方法:

        · getCode() 返回传递给构造函数的代码

        · getMessage() 返回传递给构造函数的消息

        · getFile() 返回产生异常的代码文件的完整路径

        · getLine() 返回代码文件中产生异常的代码行号

        · getTrace() 返回一个包含了产生异常的代码回退路径的数组

        · getTraceAsString() 返回与getTrace()方向相同的信息,该信息将被格式化成一个字符串。

        · _toString() 允许简单地显示一个Exception对象,并且给出以上所有方法可以提供的信息。

      通过执行以下命令,可以获得相同的异常信息(以及代码回退路径):

    echo $e;

      回退路径显示了在发生异常时所执行的函数。

     

    2.异常控制结构

      异常处理的基本思想是代码在try代码块被调用执行。在PHP中,异常必须手动抛出。

      异常控制结构:try...throw...catch

      可以将多个catch代码块与一个try代码块进行关联。还可以在一个catch代码块产生新的异常。

      如下代码抛出并捕获一个异常:

    <?php
    
    try  {
    
      throw new Exception("A terrible error has occurred", 42);
    
    }
    
    catch (Exception $e) {
    
      echo "Exception ". $e->getCode(). ": ". $e->getMessage()."<br />".
    
      " in ". $e->getFile(). " on line ". $e->getLine(). "<br />";
    
    }
    
    ?>

      这里我们使用了exception类的前四个方法,catch代码块报告了异常错误信息以及发生错误位置的说明。

     

    3.用户自定义异常

      可以扩展Exception类来创建自己的异常类。

      可能需要继承的代码:

     

    <?php 
    class Exception{
        function __construct(string $message=NULL,int $code=0){
            if(func_num_args()){
                $this->message = $message;
            }
            $this->code = $code;
            $this->file = __FILE__;    // of throw clause
            $this->line = __LINE__; // of throw clause
            $this->trace = debug_backtrace();
            $this->string = StringFormat($this);
        }
    
        protected $message = "Unknown exception ";    // exception message
        protected $code = 0;    // user defined exception code
        protected $file;    // source filename of exception
        protected $line;    // source line of exception
    
        private $trace;    // backtrace of exception
        private $string;    // internal only!!
    
        final function getMessage(){
            return $this->message;
        }
        final function getCode(){
            return $this->code;
        }
        final function getFile(){
            return $this->file;
        }
        final function getTrace(){
            return $this->trace;
        }
        final function getTraceAsString(){
            return self::TraceFormat($this);
        }
        function _toString(){
            return $this->string;
        }
        static private function StringFormat(Exception $exception){
            // ... a function not available in PHP scripts
            // that returns all relevant information as a string
        }
        static private function TraceFormat(Exception $exception){
            // ... a function not available in PHP scripts
            // that returns the backtrace as a string
        }
    }
    ?>

      该类的大多数公有方法都是final的:这就意味着不能重载这些方法。我们可以创建自己的Exception子类,但是不能改变这些基本方法的行为。请注意,_toString()函数可以重载,因此我们可以改变异常的显示方式。也可以添加自己的方法。

      用户自定义的Exception类示例:

     

    <?php
    
    class myException extends Exception
    {
      function __toString()
      {
           return "<table border="1">
           <tr>
           <td><strong>Exception ".$this->getCode()."
           </strong>: ".$this->getMessage()."<br />"."
           in ".$this->getFile()." on line ".$this->getLine()."
           </td>
           </tr>
           </table><br />";
       }
    }
    
    try
    {
      throw new myException("A terrible error has occurred", 42);
    }
    catch (myException $m)
    {
       echo $m;
    }
    
    ?>

     

      在以上代码中,我们声明了一个新的异常类myException,该类扩展了Exception基类。该类与Exception类之间的差异在于重载了_toString()方法,从而为打印异常提供了一个更好的方法。

    4.文件I/O相关的异常

      写文件时可能会出现三种情况的错误:文件无法打开、无法获得写锁或者文件无法写入。我们为每一种可能性都创建了一个异常类:

     

    <?php
    
    class fileOpenException extends Exception
    {
      function __toString()
      {
           return "fileOpenException ". $this->getCode()
                  . ": ". $this->getMessage()."<br />"." in "
                  . $this->getFile(). " on line ". $this->getLine()
                  . "<br />";
       }
    }
    
    class fileWriteException extends Exception
    {
      function __toString()
      {
           return "fileWriteException ". $this->getCode()
                  . ": ". $this->getMessage()."<br />"." in "
                  . $this->getFile(). " on line ". $this->getLine()
                  . "<br />";
       }
    }
    
    class fileLockException extends Exception
    {
      function __toString()
      {
           return "fileLockException ". $this->getCode()
                  . ": ". $this->getMessage()."<br />"." in "
                  . $this->getFile(). " on line ". $this->getLine()
                  . "<br />";
       }
    }
    
    ?>

      Exception类的这些子类并没有执行任何特别的操作。事实上,对于这个应用程序的作用来说,可以让它们成为空的子类或者使用PHP所提供的Exception类。然而,我们为每个子类提供了_toString()方法,从而可以解释所发生的异常类型:

     

    <?php
    
      require_once("file_exceptions.php");
    
      // create short variable names
      $tireqty = $_POST['tireqty'];
      $oilqty = $_POST['oilqty'];
      $sparkqty = $_POST['sparkqty'];
      $address = $_POST['address'];
    
      $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
    ?>
    <html>
    <head>
      <title>Bob's Auto Parts - Order Results</title>
    </head>
    <body>
    <h1>Bob's Auto Parts</h1>
    <h2>Order Results</h2>
    <?php
    $date = date('H:i, jS F');
    
    echo "<p>Order processed at ".$date."</p>";
    
    echo '<p>Your order is as follows: </p>';
    
    $totalqty = 0;
    $totalqty = $tireqty + $oilqty + $sparkqty;
    echo "Items ordered: ".$totalqty."<br />";
    
    if( $totalqty == 0) {
      echo "You did not order anything on the previous page!<br />";
    } else {
      if ( $tireqty > 0 ) {
        echo $tireqty." tires<br />";
      }
      if ( $oilqty > 0 ) {
        echo $oilqty." bottles of oil<br />";
      }
      if ( $sparkqty > 0 ) {
        echo $sparkqty." spark plugs<br />";
      }
    }
    
    $totalamount = 0.00;
    
    define('TIREPRICE', 100);
    define('OILPRICE', 10);
    define('SPARKPRICE', 4);
    
    $totalamount = $tireqty * TIREPRICE
                 + $oilqty * OILPRICE
                 + $sparkqty * SPARKPRICE;
    
    $totalamount=number_format($totalamount, 2, '.', ' ');
    
    echo "<p>Total of order is ".$totalamount."</p>";
    echo "<p>Address to ship to is ".$address."</p>";
    
    $outputstring = $date."	".$tireqty." tires 	".$oilqty." oil	"
                      .$sparkqty." spark plugs	$".$totalamount
                      ."	". $address."
    ";
    
    // open file for appending
    try
    {
      if (!($fp = @fopen("$DOCUMENT_ROOT/../orders/orders.txt", 'ab')))
          throw new fileOpenException();
    
      if (!flock($fp, LOCK_EX))
         throw new fileLockException();
    
      if (!fwrite($fp, $outputstring, strlen($outputstring)))
         throw new fileWriteException();
      flock($fp, LOCK_UN);
      fclose($fp);
      echo "<p>Order written.</p>";
    }
    catch (fileOpenException $foe)
    {
       echo "<p><strong>Orders file could not be opened.
             Please contact our webmaster for help.</strong></p>";
    }
    catch (Exception $e)
    {
       echo "<p><strong>Your order could not be processed at this time.
             Please try again later.</strong></p>";
    }
    
    ?>
    </body>
    </html>

      可以看到,以上脚本的文件I/O部分被封装在一个try代码块中。通常,良好的编码习惯要求try代码块的代码量较少,并且在代码块的结束处捕获相关异常。这使得异常处理代码更容易编写和维护,因为可以看到所处理的内容。

      如果无法打开文件,将抛出一个fileOpenException异常;如果无法锁定该文件,将抛出一个fileLockException异常;而如果无法写这个文件,将抛出一个fileWriteException异常。

      我们给出了两个catch代码块:一个用来处理fileOpen-Exception异常,而另一个用来处理Exception。由于其他异常都是从Exception继承过来的,它们将被第二个catch代码块捕获。catch代码块与每一个instanceof操作符相匹配。这就是为每一个类扩展自己异常类的理由。

      如果异常没有匹配的catch语句块,PHP将报告一个致命错误。

      请注意fopen()函数的调用仍然使用了@错误抑制操作符前缀。如果该函数调用失败,PHP将发出一个警告,根据php.ini中的错误报告设置不同,该警告可能会被报告或者记录。无论是否产生一个异常,这个警告仍然会发出。

      好了,从零开始攻略PHP系列到这里就水完了,仅供参考,好多我也是一知半解,只是整理出来方便查阅。下个月会陆续发一些数据库的,也就是该书整理的第二篇。

     

    整理自《PHP and MySQL Web 开发》

     

  • 相关阅读:
    MXNet--DMLC-Core代码解读与宏
    mxnet的训练过程——从python到C++
    L1正则化及其推导
    mshadow的原理--MXNet
    A-Softmax的总结及与L-Softmax的对比——SphereFace
    天猫-淘宝年货精选,内部特供,最高折扣,最优质量
    get_template_part() 函数详解备忘(转)
    (转)WordPress的主查询函数-query_posts()
    深度剖析WordPress主题结构(转)
    Science上发表的超赞聚类算法(转)
  • 原文地址:https://www.cnblogs.com/xulei1992/p/5810653.html
Copyright © 2011-2022 走看看