web-dev-qa-db-fra.com

Comment puis-je attraper une "erreur fatale capturable" sur PHP?

J'essaye d'implémenter Type Hinting de PHP5 sur une de mes classes,

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, une instance de ClassWrong donnée ...

Puis-je savoir s'il est possible d'attraper cette erreur (car il dit "capturable")? et si oui, comment?

Merci.

94
hoball

Mise à jour: Ce n'est plus une erreur fatale capturable dans php 7. Au lieu de cela, une "exception" est levée. Une "exception" (entre guillemets effrayants) qui n'est pas dérivée de Exception mais Error ; c'est toujours un Throwable et peut être géré 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. Il 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 détectée par un handle défini par l'utilisateur (voir aussi set_error_handler () ), l'application s'interrompt 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

108
VolkerK