2012-03-19 50 views
1

我的應用程序有一個註冊的關閉功能,似乎有一些問題與我的方法與try/catch使用異常退出應用程序(而不是使用exit()方法由於FastCGI不喜歡這個)。使用異常退出PHP應用程序

我的問題是,如果try/catch塊中不是ExitApp異常引發另一個異常,它會導致一些意外的結果,最終結果是ExitApp異常未被捕獲。

我在PHP 5.3.6上看到這個,現在要在另一個版本上測試它,但我很好奇,如果任何人都可以立即指出這裏有什麼問題。

<?php 

// Define dummy exception class 
class ExitApp extends Exception {} 

try { 
    // Define shutdown function 
    function shutdown() { 
     echo "Shutting down..."; 
     throw new ExitApp; 
    } 

    register_shutdown_function("shutdown"); 

    // Throw exception! 
    throw new Exception("EXCEPTION!"); 
} catch(ExitApp $e) { 
    echo "Catching the exit exception!"; 
} 

/** 
* Expected Result: Uncaught Exception Error and then "Catching the exit exception!" is printed. 
* Actual Result: Uncaught Exception Error for "Exception" and then Uncaught Exception Error for "ExitApp" even though it's being caught. 
*/ 

回答

0

您對代碼有錯誤的期望。首先,如果在關閉函數中拋出異常,那麼最終會導致未捕獲的異常 - 在tr/catch塊之外調用關閉函數。

其次你沒有試圖攔截未知的異常 - 你只能捕獲ExitApp類型。你可能想嘗試這樣的事情:

try { 
    //some stuff 
} catch(ExitApp $ea) { 
    //normal exit, nothing to do here 
} catch(Exception $e){ 
    //something rather unexpected, log it 
} 
+0

示例代碼已經過調整以更好地反映我的真實情況。至於捕捉其他異常,這是重點。我只想捕捉ExitApp異常並且不執行任何操作。所有其他異常將被全局異常處理程序捕獲。 – saverio 2012-03-19 18:34:34

+0

您的更改變化不大。第一次使用關閉功能時引發異常,而不是定義函數的位置。更重要的是,關閉函數在退出,致命錯誤和未捕獲異常之後被調用,因此您不應該將其註冊爲關閉函數。讓腳本正常進行到最後,並在必要時拋出它。如果我理解正確,只要在註冊爲shutdown的地方調用'shutdown()',那麼任何代碼都不會被執行,所以不會有未捕獲的異常。 – 2012-03-19 18:43:26

+0

看來這裏面臨的更大問題是異常無法通過關閉函數內的try/catch捕獲。看起來,當關閉功能被調用時,它們將不在標準範圍內。我在設計這個解決方案時並沒有意識到。 – saverio 2012-03-19 19:19:53

0

關機()函數甚至沒有在try/catch塊,所以它永遠不會跳下來捕捉這個異常類型。它將在出口上運行,這樣您就不會再在該try/catch塊中。

在更精神上,try/catch並不意味着流量控制。我不太確定你爲什麼試圖拋出這個腳本來導致腳本退出,而不是僅僅調用你自己的shutdown()方法。

希望有所幫助。

+0

該代碼僅僅是這篇文章嘲諷的樣本,但你在所有方面都是正確的。永遠不要少,它不能解決我的任何問題。我沒有調用我自己的shutdown()方法的原因是因爲如果我在我的應用程序內部深處並且想要退出應用程序,那麼必須調用exit(),否則腳本將繼續運行。正如我上面所解釋的,當您的應用程序通過FastCGI運行時調用exit()並不會很好。 Python使用SystemExit異常,並將該概念移植到PHP。它運作良好;但是,在這種情況下,並非如此。 – saverio 2012-03-19 18:25:35