目錄
一、PHP中的異常簡介及使用
1.1 異常執行流程
1.2 PHP異常特徵
1.3 PHP內建異常
#1.4 錯誤與例外的差異
1.4.1 例外處理
2.3 使用观察者模式处理异常信息
三、自定义异常处理器
3.1 如何自定义异常处理器
3.1.1 自定义异常处理器
3.1.2 错误/异常之后是否继续执行代码问题总结
3.2 像处理异常一样处理PHP错误
3.2.1 方式一:ErrorException
3.2.2 方式二:自定义异常类,继承基类Exception
3.3 PHP页面重定向实现
首頁 後端開發 php教程 PHP程式設計師遇到的錯誤與異常下篇之異常

PHP程式設計師遇到的錯誤與異常下篇之異常

Apr 14, 2018 pm 03:02 PM
php 程式設計師

本篇文章介紹的內容是PHP程式設計師遇到的錯誤與異常中的異常問題,現在分享給大家,有需要的朋友可以參考一下

上一篇:那些年,PHPer遇到的錯誤與異常:上篇之錯誤

一、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程式設計師遇到的錯誤與異常下篇之異常

PHP程式設計師遇到的錯誤與異常下篇之異常

#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 時,一般Exception基底類別放在最後,基底類別可以呼叫自訂例外類別定義的方法

  4. /**
     * 自定义异常类
     * 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();
    }
    登入後複製
2.2 小技巧

//将错误用错误抑制符吸收,然后抛出异常
If(@!fwrite($filename,$data)) throw new exception(自定义异常)

PHP_EOL #换行符
登入後複製

     記錄錯誤日誌資訊方式:

(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程式設計師遇到的錯誤與異常下篇之異常的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
<🎜>掩蓋:探險33-如何獲得完美的色度催化劑
2 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1677
14
CakePHP 教程
1430
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP的目的:構建動態網站 PHP的目的:構建動態網站 Apr 15, 2025 am 12:18 AM

PHP用於構建動態網站,其核心功能包括:1.生成動態內容,通過與數據庫對接實時生成網頁;2.處理用戶交互和表單提交,驗證輸入並響應操作;3.管理會話和用戶認證,提供個性化體驗;4.優化性能和遵循最佳實踐,提升網站效率和安全性。

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

為什麼要使用PHP?解釋的優點和好處 為什麼要使用PHP?解釋的優點和好處 Apr 16, 2025 am 12:16 AM

PHP的核心優勢包括易於學習、強大的web開發支持、豐富的庫和框架、高性能和可擴展性、跨平台兼容性以及成本效益高。 1)易於學習和使用,適合初學者;2)與web服務器集成好,支持多種數據庫;3)擁有如Laravel等強大框架;4)通過優化可實現高性能;5)支持多種操作系統;6)開源,降低開發成本。

PHP的影響:網絡開發及以後 PHP的影響:網絡開發及以後 Apr 18, 2025 am 12:10 AM

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

PHP與Python:用例和應用程序 PHP與Python:用例和應用程序 Apr 17, 2025 am 12:23 AM

PHP適用於Web開發和內容管理系統,Python適合數據科學、機器學習和自動化腳本。 1.PHP在構建快速、可擴展的網站和應用程序方面表現出色,常用於WordPress等CMS。 2.Python在數據科學和機器學習領域表現卓越,擁有豐富的庫如NumPy和TensorFlow。

繼續使用PHP:耐力的原因 繼續使用PHP:耐力的原因 Apr 19, 2025 am 12:23 AM

PHP仍然流行的原因是其易用性、靈活性和強大的生態系統。 1)易用性和簡單語法使其成為初學者的首選。 2)與web開發緊密結合,處理HTTP請求和數據庫交互出色。 3)龐大的生態系統提供了豐富的工具和庫。 4)活躍的社區和開源性質使其適應新需求和技術趨勢。

See all articles