PHPタイプのヒントで「キャッチ可能な致命的なエラー」をキャッチするにはどうすればよいですか?


96

私のクラスの1つにPHP5のタイプヒントを実装しようとしています。

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);

キャッチ可能な致命的なエラー:ClassA :: method_a()に渡される引数1はClassBのインスタンスでなければなりません。指定されたClassWrongのインスタンス...

そのエラーをキャッチすることは可能ですか(「キャッチ可能」と表示されているため)?はいの場合、どうやって?


4
将来の参考のために:エンジンの例外(PHP 7の場合) -PHP 7以降、致命的なエラーをキャッチできるようになりました。これは、ここで説明のためでもあり、「キャッチできる致命的なエラー」E_RECOVERABLE_ERRORこれらはPHP 7で始まるcatchedすると...)
hakre

回答:


113

更新:これは、php 7ではもはやキャッチ可能な致命的なエラーではありません。代わりに、「例外」がスローされます。由来していない(恐怖引用符で)「例外」の例外が、エラー。それでもThrowableであり、通常のtry-catchブロックで処理できます。https://wiki.php.net/rfc/throwable-interfaceを参照してください

例えば

<?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)キャッチ
可能な致命的なエラー。おそらく危険なエラーが発生しましたが、エンジンが不安定な状態のままではありませんでした。エラーがユーザー定義のハンドル(set_error_handler()も参照によってキャッチされない場合、アプリケーションは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


1
もちろん、これは致命的なエラーと非常によく似ていますが、サーバーログを調べても見つからないという点が異なります。ありがとうphp:/
John Hunt

3
つまり、キャッチ可能なエラーをキャッチすることはできません。素晴らしい!
Paul d'Aoust 2016年

@Paul何があなたをこの結論に導きましたか?
VolkerK 2016年

3
ああ、私はそれが伝統的な意味で(try / catchブロックを使用して)キャッチできないことを意味しました。私はその日PHPについて不機嫌だっただけだったので、まったく異なる意味で「キャッチ可能」であることがわかったとき、コメントせざるを得なくなりました。あなたの素晴らしい答えに反対することは何もありません(実際、私は賛成しています)。私の怒りはすべてPHP自体に対するものでした!
Paul d'Aoust

そして私は、私が何か;-)見落としてきたと思っblog.codinghorror.com/php-sucks-but-it-doesnt-matter D:
VolkerK
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.