Wie kann ich einen "abfangbaren schwerwiegenden Fehler" bei Hinweisen auf PHP-Typen abfangen?

96

Ich versuche, Type Hinting von PHP5 in einer meiner Klassen zu implementieren.

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

class ClassB {}
class ClassWrong{}

Richtige Benutzung:

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

Fehler erzeugen:

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

Auffangbarer schwerwiegender Fehler: Argument 1, das an ClassA :: method_a () übergeben wurde, muss eine Instanz von ClassB sein, eine Instanz von ClassWrong ist angegeben ...

Ist es möglich, diesen Fehler abzufangen (da dort "catchable" steht)? und wenn ja, wie?

hoball
quelle
4
Zum späteren Nachschlagen: Ausnahmen in der Engine (für PHP 7) - Ab PHP 7 können schwerwiegende Fehler auftreten. Dies gilt auch für den hier diskutierten "Catchable Fatal Error" ( E_RECOVERABLE_ERROR), da diese ab PHP 7
abgefangen werden

Antworten:

113

Update: Dies ist in PHP 7 kein schwerwiegender Fehler mehr. Stattdessen wird eine "Ausnahme" ausgelöst. Eine „Ausnahme“ (in Schrecken Anführungszeichen) , die nicht von abgeleiteter Ausnahme aber Fehlern ; Es ist immer noch ein Throwable und kann mit einem normalen Try-Catch-Block gehandhabt werden. Siehe https://wiki.php.net/rfc/throwable-interface

Z.B

<?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.';

druckt

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.

Alte Antwort für Pre-PHP7-Versionen:
http://docs.php.net/errorfunc.constants sagt:

E_RECOVERABLE_ERROR (Ganzzahl)
Fangender schwerwiegender Fehler. Es zeigt an, dass ein wahrscheinlich gefährlicher Fehler aufgetreten ist, der Motor jedoch nicht in einem instabilen Zustand belassen wurde. Wenn der Fehler nicht von einem benutzerdefinierten Handle abgefangen wird (siehe auch set_error_handler () ), wird die Anwendung abgebrochen, da es sich um ein E_ERROR handelt.

Siehe auch: http://derickrethans.nl/erecoverableerror.html

z.B

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.';

druckt

'catched' catchable fatal error
done.

edit: Aber du kannst es zu einer Ausnahme machen, die du mit einem Try-Catch-Block behandeln kannst

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.';

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

VolkerK
quelle
1
Dies verhält sich natürlich wie ein schwerwiegender Fehler, außer wenn Sie in Ihren Serverprotokollen nachsehen, werden Sie ihn nicht finden. Danke php: /
John Hunt
3
Mit anderen Worten, Sie können keinen abfangbaren Fehler abfangen. Wunderbar!
Paul d'Aoust
@ Paul, was bringt dich zu diesem Schluss?
VolkerK
3
Oh, ich meinte nur, dass es im herkömmlichen Sinne nicht fangbar ist (mit einem Try / Catch-Block). Ich war an diesem Tag nur mürrisch in Bezug auf PHP. Als ich herausfand, dass es in einem ganz anderen Sinne „fangbar“ ist, fühlte ich mich gezwungen, Kommentare abzugeben. Nichts gegen deine wundervolle Antwort (die ich tatsächlich positiv bewertet habe); Mein ganzer Zorn war für PHP selbst!
Paul d'Aoust
Und ich dachte, ich hätte etwas übersehen ;-) blog.codinghorror.com/php-sucks-but-it-doesnt-matter : D
VolkerK