2013-03-12 79 views
3

模擬finally子句的最佳做法是什麼?我意識到這可能被認爲是相關的(雖然我不認爲它是重複的)this questionPHP finally條款

然而,在我來說,我想處理異常,我想最終使用(或任何PHP等同或實習)的蟒蛇定義:

一個finally從句總是離開try語句前執行,是否發生異常。

只是在try-catch塊之後鬆散地編寫代碼看起來對我來說很醜陋。

回答

7

RFC for adding finally to PHP,他們提出以下解決方法:

<?php 
$db = mysqli_connect(); 
try { 
    call_some_function($db); 
} catch (Exception $e) { 
    mysqli_close($db); 
    throw $e; 
} 
mysql_close($db); 

所以,除非你升級到PHP 5.5(它將包含finally結構),這可能是你最好的選擇。

+0

可以創建一個在catch塊和整個try-catch塊之後被調用以避免重複代碼的lambda,儘管如果代碼嚴重依賴於範圍中定義的變量,這很容易變得不切實際。太糟糕php中的Lambdas不像JS那樣繼承範圍鏈。 – Mahn 2013-03-12 19:44:48

+0

@Mahn PHP沒有作用域鏈,超級全局變量以外的所有變量都被限制在當前函數中,因此關閉工作方式不同會很奇怪。 – IMSoP 2013-03-12 19:52:41

+0

@Mahn所有不合格的變量名稱,即。實際上,我還想到另外一個例外:由於某種原因,'$ this'「落入了靜態函數的範圍,即使在當前類之外。 – IMSoP 2013-03-12 20:35:44

2

PHP 5.5和更高版本確實有finally構造。

從文檔:

try { 
    echo inverse(5) . "\n"; 
} catch (Exception $e) { 
    echo 'Caught exception: ', $e->getMessage(), "\n"; 
} finally { 
    echo "First finally.\n"; 
} 
+2

或者,因爲它還沒有在技術上發佈,所以PHP 5.5和更高版本*將*具有'finally'構造;) – IMSoP 2013-03-12 19:35:39

+0

考慮到5.5是在5天前發佈的alpha,不是一個非常有用的答案。 – lafor 2013-03-12 19:36:02

+1

未來證明這個問題;)認爲它已經存在了一段時間考慮多久它被討論。 – 2013-03-12 19:36:48

5

這可以被視爲非答案的東西,但也有意味着不需要finally的結構化編碼方式,如「RAII模式」(「資源Acquisition Is Initialization「),其中清理資源是在代表該資源的本地作用域變量的析構函數中完成的。

這個想法是,如果一個異常讓你脫離函數作用域,你的析構函數將會被觸發,所以你的清理就像預期的那樣發生。如果沒有拋出異常,你會到達函數的末尾,並且你的變量將超出範圍。

快速谷歌出現了this simple code for doing it with arbitrary callbacks

0

如果你仍然堅持5.5以前的遺留代碼,並且你不介意強制性假冒每次通話的開銷,總會有這種骯髒的小竅門。

try { 
    // do your worst to mess things up. 

    throw new Exception("finally"); 
} catch (Exception $e) { 
    //TODO: after upgrading to 5.5, make this a legit try/catch/finally 
    if (($msg = $e->getMessage()) != "finally"){ 
     // real catch 
     echo "Exception doing something :" . $msg; 
    } else { 
     // quasi finally. 
    }; 
}