Comment puis-je détecter une «erreur fatale capturable» sur les indices de type PHP?

96

J'essaye d'implémenter l'indication de type de PHP5 sur l'un de mes cours,

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

class ClassB {}
class ClassWrong{}

Usage correct:

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

produisant une erreur:

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

Erreur fatale capturable: l'argument 1 passé à ClassA :: method_a () doit être une instance de ClassB, instance de ClassWrong donnée ...

Est-il possible d'attraper cette erreur (puisqu'elle dit «capturable»)? et si oui, comment?

Hoball
la source
4
Pour référence future: Exceptions dans le moteur (pour PHP 7) - À partir de PHP 7, il est possible d'attraper des erreurs fatales. Ceci est également pour l ' «erreur fatale capturable» ( E_RECOVERABLE_ERROR) discutée ici, car elles doivent être détectées à partir de PHP 7.
hakre

Réponses:

113

Mise à jour: Ce n'est plus une erreur fatale capturable dans php 7. Au lieu de cela, une "exception" est lancée. Une "exception" (entre guillemets effrayants) qui n'est pas dérivée d'une exception mais d'une erreur ; c'est toujours un Throwable et peut être manipulé avec un bloc try-catch normal. voir https://wiki.php.net/rfc/throwable-interface

Par exemple

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

impressions

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.

Ancienne réponse pour les versions pré-php7:
http://docs.php.net/errorfunc.constants dit:

E_RECOVERABLE_ERROR (entier)
Erreur fatale capturable. Cela indique qu'une erreur probablement dangereuse s'est produite, mais n'a pas laissé le moteur dans un état instable. Si l'erreur n'est pas interceptée par un handle défini par l'utilisateur (voir aussi set_error_handler () ), l'application abandonne car il s'agissait d'un E_ERROR.

voir aussi: http://derickrethans.nl/erecoverableerror.html

par exemple

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

impressions

'catched' catchable fatal error
done.

edit: Mais vous pouvez "en faire" une exception que vous pouvez gérer avec un bloc 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.';

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

VolkerK
la source
1
Donc, bien sûr, cela se comporte beaucoup comme une erreur fatale, sauf que lorsque vous regardez dans les journaux de votre serveur, vous ne le trouverez pas. Merci php: /
John Hunt
3
donc en d'autres termes, vous ne pouvez pas attraper une erreur détectable. Merveilleux!
Paul d'Aoust
@Paul qu'est-ce qui vous amène à cette conclusion?
VolkerK
3
Oh, je voulais juste dire qu'il n'était pas capturable au sens traditionnel (en utilisant un bloc try / catch). Je me sentais juste grincheux à propos de PHP ce jour-là, alors quand j'ai découvert qu'il était «capturable» dans un sens totalement différent, je me suis senti obligé de commenter. Rien contre votre merveilleuse réponse (qui en fait j'ai voté pour); toute ma colère était pour PHP lui-même!
Paul d'Aoust
Et je pensais avoir oublié quelque chose ;-) blog.codinghorror.com/php-sucks-but-it-doesnt-matter : D
VolkerK