¿Cómo puedo detectar un "error fatal detectable" en las sugerencias de tipo PHP?

96

Estoy tratando de implementar Type Hinting de PHP5 en una de mis clases,

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

class ClassB {}
class ClassWrong{}

Uso Correcto:

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

produciendo error:

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

Error fatal detectable: el argumento 1 pasado a ClassA :: method_a () debe ser una instancia de ClassB, instancia de ClassWrong dada ...

¿Es posible detectar ese error (ya que dice "capturable")? y si es así como

hoball
fuente
4
Para referencia futura: Excepciones en el motor (para PHP 7) - A partir de PHP 7 es posible detectar errores fatales. Esto también es para el "Error fatal detectable" aquí discutido ( E_RECOVERABLE_ERROR) ya que estos se detectan a partir de PHP 7 ..
hakre

Respuestas:

113

Actualización: Este ya no es un error fatal detectable en php 7. En cambio, se lanza una "excepción". Una "excepción" (entre comillas de miedo) que no se deriva de Exception sino de Error ; sigue siendo un Throwable y se puede manejar con un bloque try-catch normal. ver https://wiki.php.net/rfc/throwable-interface

P.ej

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

huellas dactilares

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.

Respuesta anterior para versiones anteriores a php7:
http://docs.php.net/errorfunc.constants dice:

E_RECOVERABLE_ERROR (integer)
Error fatal detectable. Indica que ocurrió un error probablemente peligroso, pero no dejó el motor en un estado inestable. Si el error no es detectado por un identificador definido por el usuario (ver también set_error_handler () ), la aplicación aborta como si fuera un E_ERROR.

ver también: http://derickrethans.nl/erecoverableerror.html

p.ej

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

huellas dactilares

'catched' catchable fatal error
done.

editar: Pero puede "convertirlo" en una excepción que puede manejar con un bloque 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.';

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

VolkerK
fuente
1
Entonces, por supuesto, esto se comporta de manera muy similar a un error fatal, excepto que cuando miras en los registros de tu servidor no lo encontrarás. Gracias php: /
John Hunt
3
en otras palabras, no puede detectar un error detectable. ¡Maravilloso!
Paul d'Aoust
@Paul, ¿qué te trae a esta conclusión?
VolkerK
3
Oh, solo quise decir que no era capturable en el sentido tradicional (usando un bloque try / catch). Ese día me sentía malhumorado por PHP, así que cuando descubrí que era "atrapable" en un sentido totalmente diferente, me sentí obligado a comentar. Nada en contra de su maravillosa respuesta (que de hecho voté a favor); ¡toda mi ira fue por PHP mismo!
Paul d'Aoust
Y pensé que había pasado por alto algo ;-) blog.codinghorror.com/php-sucks-but-it-doesnt-matter : D
VolkerK