1. 程式人生 > >2017.8.10

2017.8.10

execute 成功 spl port 一個 所有 ted 函數的原型 ()

一、PHP的錯誤和異常處理

1、異常與錯誤的概述
  PHP中什麽是異常:
  程序在運行中出現不符合預期的情況,允許發生(你也不想讓他出現不正常的情況)但他是一種不正常的情況,按照我們的正常邏輯本不該出的錯誤,但仍然會出現的錯誤,屬於邏輯和業務流程的錯誤,而不是編譯或者語法上的錯誤。
  PHP中什麽是錯誤:
  屬於php腳本自身的問題,大部分情況是由錯誤的語法,服務器環境導致,使得編譯器無法通過檢查,甚至無法運行的情況。warning、notice都是錯誤,只是他們的級別不同而已,並且錯誤是不能被try-catch捕獲的。

2、ERROR的級別
  只有熟悉錯誤級別才能對錯誤捕捉有更好的認識。 ERROR有不同的錯誤級別:

 Fatal Error:致命錯誤(腳本終止運行)
          E_ERROR         // 致命的運行錯誤,錯誤無法恢復,暫停執行腳本
          E_CORE_ERROR    // PHP啟動時初始化過程中的致命錯誤
          E_COMPILE_ERROR // 編譯時致命性錯,就像由Zend腳本引擎生成了一個E_ERROR
          E_USER_ERROR    // 自定義錯誤消息。像用PHP函數trigger_error(錯誤類型設置為:E_USER_ERROR)
  
     Parse Error:編譯時解析錯誤,語法錯誤(腳本終止運行)
          
E_PARSE //編譯時的語法解析錯誤 Warning Error:警告錯誤(僅給出提示信息,腳本不終止運行) E_WARNING // 運行時警告 (非致命錯誤)。 E_CORE_WARNING // PHP初始化啟動過程中發生的警告 (非致命錯誤) 。 E_COMPILE_WARNING // 編譯警告 E_USER_WARNING // 用戶產生的警告信息 Notice Error:通知錯誤(僅給出通知信息,腳本不終止運行) E_NOTICE // 運行時通知。表示腳本遇到可能會表現為錯誤的情況.
E_USER_NOTICE // 用戶產生的通知信息。

  由此可知有5類是產生ERROR級別的錯誤,這種錯誤直接導致PHP程序退出可以定義成: ERROR = E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_PARSE

如果希望在PHP腳本中,遇到以上某個錯誤時,報告錯誤消息,必須在配置文件php.ini中將display_errors指令的值設置為On,來開啟PHP輸出錯誤報告的功能。

在PHP腳本中調用ini_set()函數,強制在該腳本中啟動display_errors指令。並通過error_reporting()函數設置錯誤級別為E_ALL,報告所有錯誤警告和註意。

3、自定義錯誤處理

1:set_error_handler()
  看到這個名字估計就知道什麽意思了,這個函數用於捕獲錯誤,設置一個用戶自定義的錯誤處理函數。

 <?php
     set_error_handler(‘zyferror‘);//使用此句把錯誤的處理交給用戶自定義的函數zyferror();處理,error_reporting()函數將會失效。
     function zyferror($type, $message, $file, $line)
     {
       var_dump(‘<b>set_error_handler: ‘ . $type . ‘:‘ . $message . ‘ in ‘ . $file . ‘ on ‘ . $line . ‘ line .</b><br />‘);
     }
 ?>

  當程序出現錯誤的時候自動調用此方法,不過需要註意一下兩點:第一,如果存在該方法,相應的error_reporting()就不能在使用了。所有的錯誤都會交給自定義的函數處理。第二,此方法不能處理以下級別的錯誤:E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,set_error_handler() 函數所在文件中產生的E_STRICT,該函數只能捕獲系統產生的一些Warning、Notice級別的錯誤

  並且他有多種調用的方法

<?php
      // 直接傳函數名 NonClassFunction
      set_error_handler(‘function_name‘); 
 
      // 傳 class_name && function_name
      set_error_handler(array(‘class_name‘, ‘function_name‘)); 
 ?>

2:register_shutdown_function()
  捕獲PHP的錯誤:Fatal Error、Parse Error等,這個方法是PHP腳本執行結束前最後一個調用的函數,比如腳本錯誤、die()、exit、異常、正常結束都會調用,多麽牛逼的一個函數啊!通過這個函數就可以在腳本結束前判斷這次執行是否有錯誤產生,這時就要借助於一個函數:error_get_last();這個函數可以拿到本次執行產生的所有錯誤error_get_last();返回的信息
  [type] - 錯誤類型
  [message] - 錯誤消息
  [file] - 發生錯誤所在的文件
  [line] - 發生錯誤所在的行

<?php
    register_shutdown_function(‘zyfshutdownfunc‘);//在退出腳本前,調用並執行在該函數中註冊的函數。
     function zyfshutdownfunc()
     {
         if ($error = error_get_last()) //通過error_get_last()函數獲取錯誤信息,賦值給$error數組,通過下面語句打印輸出錯誤信息
{
var_dump(‘<b>register_shutdown_function: Type:‘ . $error[‘type‘] . ‘ Msg: ‘ . $error[‘message‘] . ‘ in ‘ . $error[‘file‘] . ‘ on line ‘ . $error[‘line‘] . ‘</b>‘); } }
      var_dump(23+-+); //此處語法錯誤
echo "test";//函數會在輸出此句後,打印出上面一句的錯誤
?>

 通過這種方法就可以巧妙的打印出程序結束前所有的錯誤信息

 3:set_exception_handler()
  設置默認的異常處理程序,用在沒有用try/catch塊來捕獲的異常,也就是說不管你拋出的異常有沒有人捕獲,如果沒有人捕獲就會進入到該方法中,並且在回調函數調用後異常會中止。看一下用法:

1 <?php
2     set_exception_handler(‘zyfexception‘);//自定義異常處理函數,腳本程序會在異常處理程序執行結束後停止執行
3     function zyfexception($exception)
4     {
5         var_dump("<b>set_exception_handler: Exception: " . $exception->getMessage()  . ‘</b>‘);
6     }
7     throw new Exception("zyf exception");
8 ?>

以上內容來自: http://www.cnblogs.com/zyf-zhaoyafei/p/6928149.html。

4、錯誤日誌

對於PHP開發者來說,一旦某個產品投入使用,應該立即將display_errors選項關閉,以免因為這些錯誤所透露的路徑、數據庫連接、數據表等信息而遭到黑客攻擊。但是,任何一個產品在投入使用後,都難免會有錯誤出現,那麽如何記錄一些對開發者有用的錯誤報告呢?我們可以在單獨的文本文件中將錯誤報告作為日誌記錄。錯誤日誌的記錄,可以幫助開發人員或者管理人員查看系統是否存在問題。

如果需要將程序中的錯誤報告寫入錯誤日誌中,只要在PHP的配置文件中,將配置指令log_errors開啟即可。錯誤報告默認就會記錄到Web服務器的日誌文件裏,例如記錄到Apache服務器的錯誤日誌文件error.log中。當然也可以記錄錯誤日誌到指定的文件中或發送給系統syslog,分別介紹如下:

1.使用指定的文件記錄錯誤報告日誌

如果使用自己指定的文件記錄錯誤日誌,一定要確保將這個文件存放在文檔根目錄之外,以減少遭到攻擊的可能。並且該文件一定要讓PHP腳本的執行用戶(Web服務器進程所有者)具有寫權限。假設在Linux操作系統中,將/usr/local/目錄下的error.log文件作為錯誤日誌文件,並設置Web服務器進程用戶具有寫的權限。然後在PHP的配置文件中,將error_log指令的值設置為這個錯誤日誌文件的絕對路徑。需要將php.ini中的配置指令做如下修改:

error_reporting = E_ALL ;將會向PHP報告發生的每個錯誤

display_errors = Off ;不顯示滿足上條指令所定義規則的所有錯誤報告

log_errors = On ;決定日誌語句記錄的位置

log_errors_max_len = 1024 ;設置每個日誌項的最大長度

error_log = /usr/local/error.log ;指定產生的錯誤報告寫入的日誌文件位置

PHP的配置文件按上面的方式設置完成以後,並重新啟動Web服務器。這樣,在執行PHP的任何腳本文件時,所產生的所有錯誤報告都不會在瀏覽器中顯示,而會記錄在自己指定的錯誤日誌/usr/local/error.log中。此外,不僅可以記錄滿足error_reporting所定義規則的所有錯誤,而且還可以使用PHP中的error_log()函數,送出一個用戶自定義的錯誤信息。該函數的原型如下所示:

bool error_log ( string message [, int message_type [, string destination [, string extra_headers]]] )

此函數會送出錯誤信息到Web服務器的錯誤日誌文件、某個TCP服務器或到指定文件中。該函數執行成功則返回TRUE,失敗則返回FALSE。第一個參數message 是必選項,即為要送出的錯誤信息。如果僅使用這一個參數,會按配置文件php.ini中所設置的位置處發送消息。第二個參數message_type為整數值:0表示送到操作系統的日誌中;1則使用PHP的Mail()函數,發送信息到某E-mail處,第四個參數extra_headers亦會用到;2則將錯誤信息送到TCP 服務器中,此時第三個參數destination表示目的地IP及Port;3則將信息存到文件destination中。

5、 異常處理

異常(Exception)處理用於指定的錯誤發生時改變腳本的正常流程,是PHP 5中的一個新的重要特性。異常處理是一種可擴展、易維護的錯誤處理統一機制,並提供了一種新的面向對象的錯誤處理方式。

1.異常處理實現

異常處理和編寫程序的流程控制相似,所以也可以通過異常處理實現一種另類的條件選擇結構。異常就是在程序運行過程中出現的一些意料之外的事件,如果不對此事件進行處理,則程序在執行時遇到異常將崩潰。處理異常需要在PHP腳本中使用以下語句:

try {                     //所有需要進行異常處理的代碼都必須放入這個代碼塊內

   … …                  //在這裏可以使用throw語句拋出一個異常對象

}catch(ex1) {               //使用該代碼塊捕獲一個異常,並進行處理

   … …                 //處理發生的異常,也可再次拋出異常

}

在PHP代碼中所產生的異常可以被throw語句拋出並被catch語句捕獲需要進行異常處理的代碼都必須放入try代碼塊內,以便捕獲可能存在的異常。每一個try至少要有一個與之對應的catch,也不能出現單獨的catch,另外try和cache之間也不能有任何的代碼出現。一個異常處理的簡單實例如下所示:

<?php

         try {
                   $error = ‘Always throw this error‘;

                   throw new Exception($error);      //創建一個異常對象,通過throw語句拋出

                   echo ‘Never executed‘;            //從這裏開始,try代碼塊內的代碼將不會再被執行

         } catch (Exception $e) {

                   echo ‘Caught exception: ‘,  $e->getMessage(), "\n";  //輸出捕獲的異常消息
         }

         echo ‘Hello World‘;                    //程序沒有崩潰繼續向下執行

?>

在上面的代碼中,如果try代碼塊中出現某些錯誤,我們就可以執行一個拋出異常的操作。在某些編程語言中,例如Java,在出現異常時將自動拋出異常。而在PHP中,異常必須手動拋出。throw關鍵字將觸發異常處理機制,它是一個語言結構,而不是一個函數,但必須給它傳遞一個對象作為值。在最簡單的情況下,可以實例化一個內置的Exception類,就像以上代碼所示那樣。如果在try語句中有異常對象被拋出,該代碼塊不會再繼續向下執行,而直接跳轉到catch中執行。並傳遞給catch代碼塊一個對象,也可以理解為被catch代碼塊捕獲的對象,其實就是導致異常被throw語句拋出的對象。在catch代碼塊中可以簡單的輸出一些異常的原因,也可以是try代碼塊中任務的另一個版本解決方案,此外,也可以在這個catch代碼塊中產生新的異常。最重要的是,在異常處理之後,程序不會崩潰,而會繼續執行。

6、捕獲多個異常

在try代碼塊之後,必須至少給出一個catch代碼塊,也可以將多個catch代碼塊與一個try代碼塊進行關聯。如果每個catch代碼塊可以捕獲一個不同類型的異常,那麽使用多個catch就可以捕獲不同的類所產生的異常。當產生一個異常時,PHP將查詢一個匹配的catch代碼塊。如果有多個catch代碼塊,傳遞給每一個catch代碼塊的對象必須具有不同的類型,這樣PHP可以找到需要進入哪一個catch代碼塊。當try代碼塊不再拋出異常或者找不到catch能匹配所拋出的異常時,PHP代碼就會在跳轉到最後一個 catch 的後面繼續執行。多個異常的捕獲的示例如下:

內置的異常處理類(Exception)

<?php

         /* 自定義的一個異常處理類,但必須是擴展內異常處理類的子類 */
         class MyException extends Exception{
                   //重定義構造器使第一個參數 message 變為必須被指定的屬性
                   public function __construct($message, $code=0){
                            //可以在這裏定義一些自己的代碼

                            //建議同時調用 parent::construct()來檢查所有的變量是否已被賦值
                            parent::__construct($message, $code);
                   }
                   //重寫父類中繼承過來的方法,自定義字符串輸出的樣式
                   public function __toString() {
                            return __CLASS__.":[".$this->code."]:".$this->message."<br>";
                   }
                   //為這個異常自定義一個處理方法
                   public function customFunction() {
                            echo "按自定義的方法處理出現的這個類型的異常";
                   }
         }

         /* 創建一個用於測試自定義擴展的異常類MyException */
         class TestException {

                   public $var;                          //一個成員屬性,用來判斷對象是否創建成功被初始化
                   function __construct($value=0) {        //通過構造方法的傳值決定拋出的異常
                            switch($value){                 //對傳入的值進行選擇性的判斷
                                     case 1:                    //如果傳入的參數值為1,則拋出自定義的異常對象
                                               throw new MyException("傳入的值“1” 是一個無效的參數", 5);

                                               break;
                                     case 2:                      //如果傳入的參數值為2,則拋出PHP內置的異常對象
                                               throw new Exception("傳入的值“2”不允許作為一個參數", 6);

                                               break;
                                     default:                    //如果傳入的參數值合法,則不拋出異常創建對象成功
                                              $this->var=$value;      //為對象中的成員屬性賦值
                                               break;
                            }
                   }
         }

     //示例1,在沒有異常時,程序正常執行,try中的代碼全部執行並不會執行任何catch區塊
         try{
                   $testObj=new TestException();              //使用默認參數創建異常的測試類對象
                   echo "***********<br>";                 //沒有拋出異常這條語句就會正常執行
         }catch(MyException $e){                      //捕獲用戶自定義的異常區塊
                   echo "捕獲自定義的異常:$e <br>";        //按自定義的方式輸出異常消息
                   $e->customFunction();                     //可以調用自定義的異常處理方法
         }catch(Exception $e) {                         //捕獲PHP內置的異常處理類的對象
                   echo "捕獲默認的異常:".$e->getMessage()."<br>";   //輸出異常消息
         }     
         var_dump($testObj);          //判斷對象是否創建成功,如果沒有任何異常,則創建成功

    //示例2,拋出自定義的異常,並通過自定義的異常處理類捕獲這個異常並處理
         try{
                   $testObj1=new TestException(1);           //傳入參數1時,創建測試類對象拋出自定義異常
                   echo "

以上部分內容來自:http://www.cnblogs.com/laojie4321/p/4187620.html。

 

2017.8.10