2010-03-18 87 views
86

我想實現我班的一個PHP5的類型提示,如何捕捉PHP類型提示上的「可捕獲的致命錯誤」?

class ClassA { 
    public function method_a (ClassB $b) 
    {} 
} 

class ClassB {} 
class ClassWrong{} 

正確的用法:

$a = new ClassA; 
$a->method_a(new ClassB); 

產生錯誤:

$a = new ClassA; 
$a->method_a(new ClassWrong); 

Catchable fatal error: Argument 1 passed to ClassA::method_a() must be an instance of ClassB, instance of ClassWrong given...

我可以知道如果有可能捕獲該錯誤(因爲它表示「可捕獲」)?如果是,如何?

謝謝。

+2

對於未來參考:[引擎中的例外(用於PHP 7)](https://wiki.php.net/rfc/engine_exceptions_for_php7) - 從PHP 7開始,它是poss無法捕捉致命錯誤。這也是爲了這裏討論的*「可捕捉的致命錯誤」*('E_RECOVERABLE_ERROR'),因爲這些將從PHP 7開始搭配.. – hakre 2015-04-27 06:11:32

回答

98

更新:在PHP 7中,這不是一個可捕獲的致命錯誤。而是引發「異常」。一個「例外」(在恐嚇報價中)並非源自Exception,而是Error;它仍然是Throwable,可以用正常的try-catch塊來處理。見https://wiki.php.net/rfc/throwable-interface

E.g.

<?php 
class ClassA { 
    public function method_a (ClassB $b) { echo 'method_a: ', get_class($b), PHP_EOL; } 
} 
class ClassWrong{} 
class ClassB{} 
class ClassC extends ClassB {} 


foreach(array('ClassA', 'ClassWrong', 'ClassB', 'ClassC') as $cn) { 
    try{ 
     $a = new ClassA; 
     $a->method_a(new $cn); 
    } 
    catch(Error $err) { 
     echo "catched: ", $err->getMessage(), PHP_EOL; 
    } 
} 
echo 'done.'; 

打印

catched: Argument 1 passed to ClassA::method_a() must be an instance of ClassB, instance of ClassA given, called in [...] 
catched: Argument 1 passed to ClassA::method_a() must be an instance of ClassB, instance of ClassWrong given, called in [...] 
method_a: ClassB 
method_a: ClassC 
done. 

舊的答案PHP7之前的版本:
http://docs.php.net/errorfunc.constants說:

E_RECOVERABLE_ERROR (integer)
Catchable fatal error. It indicates that a probably dangerous error occured, but did not leave the Engine in an unstable state. If the error is not caught by a user defined handle (see also set_error_handler()), the application aborts as it was an E_ERROR.

還看到:http://derickrethans.nl/erecoverableerror.html

例如

function myErrorHandler($errno, $errstr, $errfile, $errline) { 
    if (E_RECOVERABLE_ERROR===$errno) { 
    echo "'catched' catchable fatal error\n"; 
    return true; 
    } 
    return false; 
} 
set_error_handler('myErrorHandler'); 

class ClassA { 
    public function method_a (ClassB $b) {} 
} 

class ClassWrong{} 

$a = new ClassA; 
$a->method_a(new ClassWrong); 
echo 'done.'; 

打印

'catched' catchable fatal error 
done. 

編輯:但是你可以 「讓」 它,你可以用一個try-catch塊處理異常

function myErrorHandler($errno, $errstr, $errfile, $errline) { 
    if (E_RECOVERABLE_ERROR===$errno) { 
    echo "'catched' catchable fatal error\n"; 
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline); 
    // return true; 
    } 
    return false; 
} 
set_error_handler('myErrorHandler'); 

class ClassA { 
    public function method_a (ClassB $b) {} 
} 

class ClassWrong{} 

try{ 
    $a = new ClassA; 
    $a->method_a(new ClassWrong); 
} 
catch(Exception $ex) { 
    echo "catched\n"; 
} 
echo 'done.'; 

見:http://docs.php.net/ErrorException

+10

謝謝!我學習一件新事物! – hoball 2010-03-18 09:23:50

+18

php有時只是愚蠢的 – Peter 2014-09-08 10:44:47

+0

所以當然,這表現非常像一個致命的錯誤,除非你在你的服務器日誌看你不會找到它。謝謝php:/ – 2016-02-10 08:46:55