try tipos que manejo manejador excepciones ejemplos custom catch php exception-handling

php - manejo - Captura de mĂșltiples tipos de excepciones en un bloque catch



try catch php 7 (10)

Actualizar:

A partir de PHP 7.1, esto está disponible.

La sintaxis es:

try { // Some code... } catch(AError | BError $e) { // Handle exceptions } catch(Exception $e) { // Handle the general case }

wiki.php.net/rfc/multiple-catch

https://github.com/php/php-src/commit/0aed2cc2a440e7be17552cc669d71fdd24d1204a

Para PHP antes de 7.1:

A pesar de lo que dicen estas otras respuestas, puede capturar AError y BError en el mismo bloque (es algo más fácil si usted es el que define las excepciones). Incluso dado que hay excepciones de las que quiere "caerse", aún debería poder definir una jerarquía que coincida con sus necesidades.

abstract class MyExceptions extends Exception {} abstract class LetterError extends MyExceptions {} class AError extends LetterError {} class BError extends LetterError {}

Entonces:

catch(LetterError $e){ //voodoo }

Como puede ver here y here , incluso las excepciones predeterminadas de SPL tienen una jerarquía que puede aprovechar. Además, como se indica en el php.net/manual/en/language.exceptions.php :

Cuando se lanza una excepción, el código que sigue a la declaración no se ejecutará, y PHP intentará encontrar el primer bloque de catch correspondiente.

Esto significa que también podrías tener

class CError extends LetterError {}

que debe manejar de forma diferente a AError o BError , por lo que su instrucción catch se vería así:

catch(CError $e){ //voodoo } catch(LetterError $e){ //voodoo }

Si tuviera el caso donde había veinte o más excepciones que legítimamente pertenecían a la misma superclase, y necesitara manejar cinco (o cualquier grupo grande grande) de una manera y el resto la otra, TODAVÍA puede hacerlo.

interface Group1 {} class AError extends LetterError implements Group1 {} class BError extends LetterError implements Group1 {}

Y entonces:

catch (Group1 $e) {}

Usar OOP cuando se trata de excepciones es muy poderoso. Usar cosas como get_class o instanceof son hacks, y deberían evitarse si es posible.

Otra solución que me gustaría agregar es poner la funcionalidad de manejo de excepciones en su propio método.

Podrías tener

function handleExceptionMethod1(Exception $e) { //voodoo } function handleExceptionMethod2(Exception $e) { //voodoo }

Suponiendo que no hay absolutamente ninguna forma de controlar las jerarquías o interfaces de la clase de excepción (y que casi siempre habrá una forma), puede hacer lo siguiente:

try { stuff() } catch(ExceptionA $e) { $this->handleExceptionMethod1($e); } catch(ExceptionB $e) { $this->handleExceptionMethod1($e); } catch(ExceptionC $e) { $this->handleExceptionMethod1($e); } catch(Exception $e) { $this->handleExceptionMethod2($e); }

De esta forma, todavía tiene una única ubicación de código único que debe modificar si su mecanismo de manejo de excepciones debe cambiar, y está trabajando dentro de las construcciones generales de OOP.

Me gustaría una forma más AError obtener la siguiente funcionalidad, para capturar AError y BError en un bloque:

try { /* something */ } catch( AError, BError $e ) { handler1( $e ) } catch( Exception $e ) { handler2( $e ) }

¿Hay alguna manera de hacer esto? ¿O tengo que atraparlos por separado?

AError y Berror tienen una clase base compartida, pero también la comparten con otros tipos de los que me gustaría pasar a handler2 , por lo que no puedo atrapar la clase base.


A partir de PHP 7.1,

catch( AError | BError $e ) { handler1( $e ) }

Curiosamente, también puedes:

catch( AError | BError $e ) { handler1( $e ) } catch (CError $e){ handler2($e); } catch(Exception $e){ handler3($e); }

y en versiones anteriores de PHP:

catch(Exception $ex){ if($ex instanceof AError){ //handle a AError } elseif($ex instanceof BError){ //handle a BError } else { throw $ex;//an unknown exception occured, throw it further } }


Además de la caída, también es posible pasar usando goto . Es muy útil si quieres ver el mundo que arde.

<?php class A_Error extends Exception {} class B_Error extends Exception {} class C_Error extends Exception {} try { throw new A_Error(); } catch (A_Error $e) { goto abc; } catch (B_Error $e) { goto abc; } catch (C_Error $e) { abc: var_dump(get_class($e)); echo "Gotta Catch ''Em All/n"; }

3v4l.org


Aquí hay una alternativa razonable si no tiene control sobre la definición de las excepciones. Use el nombre de la variable de excepción para categorizar las excepciones cuando son capturadas. Luego, verifique la variable de excepción después del bloque try / catch.

$ABError = null; try { // something } catch (AError $ABError) { // let the exception fall through } catch (BError $ABError) { // let the exception fall through } catch (Exception $e) { handler2($e); } if ($ABError) { handler1($ABError); }

Este enfoque algo extraño probablemente solo valga la pena si hay mucha duplicación entre las implementaciones del bloque catch.


Como una extensión de la respuesta aceptada, puede cambiar el tipo de excepción que resulta en un patrón que es algo así como el ejemplo original:

try { // Try something } catch (Exception $e) { switch (get_class($e)) { case ''AError'': case ''BError'': // Handle A or B break; case ''CError'': // Handle C break; case default: // Rethrow the Exception throw $e; } }


Este artículo cubre la pregunta electrictoolbox.com/php-catch-multiple-exception-types . Contenido de la publicación copiada directamente del artículo:

Ejemplos de excepciones

Aquí hay algunas excepciones de ejemplo que se han definido a los fines de este ejemplo:

class FooException extends Exception { public function __construct($message = null, $code = 0) { // do something } } class BarException extends Exception { public function __construct($message = null, $code = 0) { // do something } } class BazException extends Exception { public function __construct($message = null, $code = 0) { // do something } }

Manejando múltiples excepciones

Es muy simple: puede haber un bloque catch para cada tipo de excepción que se puede lanzar:

try { // some code that might trigger a Foo/Bar/Baz/Exception } catch(FooException $e) { // we caught a foo exception } catch(BarException $e) { // we caught a bar exception } catch(BazException $e) { // we caught a baz exception } catch(Exception $e) { // we caught a normal exception // or an exception that wasn''t handled by any of the above }

Si se lanza una excepción que no es manejada por ninguna de las otras declaraciones de captura, será manejada por el bloque catch (Exception $ e). No necesariamente tiene que ser el último.


Otra opción que no se incluye aquí es usar el atributo de code de una excepción, por lo que puede hacer algo como esto:

try { if (1 === $foo) { throw new Exception(sprintf(''Invalid foo: %s'', serialize($foo)), 1); } if (2 === $bar) { throw new Exception(sprintf(''Invalid bar: %s'', serialize($foo)), 2); } } catch (Exception $e) { switch ($e->getCode()) { case 1: // Special handling for case 1 break; case 2: // Special handling for case 2 break; default: // Special handling for all other cases } }


Si puede modificar las excepciones, use esta respuesta .

Si no puede, puede intentar capturar todo con Exception y luego verificar qué excepción se lanzó con instanceof .

try { /* something */ } catch( Exception $e ) { if ($e instanceof AError OR $e instanceof BError) { // It''s either an A or B exception. } else { // Keep throwing it. throw $e; } }

Pero probablemente sería mejor usar múltiples bloques catch como se describe en la respuesta antes mencionada .

try { /* something */ } catch( AError $e ) { handler1( $e ); } catch ( BError $b ) { handler2( $e ); }


Una buena forma es usar set_exception_handler .

¡¡¡Advertencia!!! con PHP 7, es posible que obtenga una pantalla blanca de la muerte por errores fatales. Por ejemplo, si llamas a un método en un no objeto, normalmente obtendrías un Fatal error: Call to a member function your_method() on null y esperarías ver esto si los informes de errores están Fatal error: Call to a member function your_method() on null .

El error anterior NO se catch(Exception $e) con catch(Exception $e) . El error anterior NO activará ningún manejador de error personalizado establecido por set_error_handler .

Debe usar catch(Error $e){ } para detectar errores en PHP7. . Esto podría ayudar:

class ErrorHandler{ public static function excep_handler($e) { print_r($e); } } set_exception_handler(array(''ErrorHandler'',''excep_handler''));


Viniendo en wiki.php.net/rfc/multiple-catch es la capacidad de atrapar varios tipos.

Para que esto:

<?php try { /* ... */ } catch (FirstException $ex) { $this->manageException($ex); } catch (SecondException $ex) { $this->manageException($ex); } ?>

y

<?php try { } catch (FirstException | SecondException $ex) { $this->manageException($ex); } ?>

son funcionalmente equivalentes.