Manejo de errores de PHP: die () Vs trigger_error () Vs throw Exception

119

Con respecto al manejo de errores en PHP, hasta donde sé, hay 3 estilos:

  1. die()o exit()estilo:

    $con = mysql_connect("localhost","root","password");
    
    if (!$con) {
     die('Could not connect: ' . mysql_error());
    }
  2. throw Exception estilo:

     if (!function_exists('curl_init')) {
    
          throw new Exception('need the CURL PHP extension. 
                               Recomplie PHP with curl');
        }
  3. trigger_error() estilo:

    if(!is_array($config) && isset($config)) {
            trigger_error('Error: config is not an array or is not set', E_USER_ERROR);
        }

Ahora, en el manual de PHP se utilizan los tres métodos.

  • Lo que quiero saber es qué estilo debería preferir y por qué.

  • ¿Son estos 3 reemplazos entre sí y, por lo tanto, se pueden usar indistintamente?

Ligeramente OT: ¿Soy solo yo o todos piensan que las opciones de manejo de errores de PHP son demasiadas en la medida en que confunden a los desarrolladores de PHP?

Mente curiosa
fuente
4
Estos no son "estilos". Son características de diferentes idiomas. Para diferentes propósitos.
mario
11
@mario: ¿Cuáles son los diferentes propósitos con sangría ? Por favor ilumíname :)
CuriousMind
Pones la pregunta de una manera genial. gracias por preguntar
Contador م

Respuestas:

86

El primero nunca debe usarse en código de producción, ya que transporta información irrelevante para los usuarios finales (un usuario no puede hacer nada sobre "No se puede conectar a la base de datos" ).

Lanza Excepciones si sabe que en un determinado punto de código crítico, su aplicación puede fallar y desea que su código se recupere en múltiples niveles de llamada.

trigger_error()le permite informar de errores de grano fino (mediante el uso de diferentes niveles de mensajes de error) y puede ocultar esos errores a los usuarios finales (que usan set_error_handler()), pero aún así se le muestran durante la prueba.

También trigger_error()puede producir mensajes no fatales importantes durante el desarrollo que se pueden suprimir en el código de producción mediante un controlador de errores personalizado. También puede producir errores fatales ( E_USER_ERROR) pero no se pueden recuperar. Si activa uno de esos, la ejecución del programa se detiene en ese punto. Es por eso que, para errores fatales, se deben usar Excepciones. De esta manera, tendrá más control sobre el flujo de su programa:

// Example (pseudo-code for db queries):

$db->query('START TRANSACTION');

try {
    while ($row = gather_data()) {
       $db->query('INSERT INTO `table` (`foo`,`bar`) VALUES(?,?)', ...);
    }
    $db->query('COMMIT');
} catch(Exception $e) {
    $db->query('ROLLBACK');
}

Aquí, si gather_data()simplemente graznara (usando E_USER_ERRORo die()) hay una posibilidad, las INSERTdeclaraciones anteriores habrían llegado a su base de datos, incluso si no lo hubieran deseado y no tendría control sobre lo que sucederá a continuación.

Linus Kleen
fuente
2
así que fuera de trigger_error()y lanzando excepciones: ¿cuál debo usar y cuándo?
CuriousMind
@Gaurish Vea el ejemplo agregado sobre eso.
Linus Kleen
2
Después de leer su ejemplo, creo que ahora entiendo mejor el propósito detrás de la excepción de lanzamiento. Gracias :)
CuriousMind
1
@Pacerier Eso depende de la configuración del servidor, en realidad. Un sistema puede estar configurado para autocommit por defecto, de ahí lo explícito ROLLBACK. Este ejemplo de pseudocódigo cubre ambos casos: servidores que no están configurados para autocommit ( COMMITse requiere la declaración) y aquellos que sí.
Linus Kleen
1
@LinusKleen, ¿no se desactiva la confirmación automática una vez que ejecutamos la línea query('START TRANSACTION');?
Pacerier
10

Por lo general, uso la primera forma para una depuración simple en el código de desarrollo. No se recomienda para producción. La mejor manera es lanzar una excepción, que puede detectar en otras partes del programa y manejar algunos errores.

Los tres estilos no son reemplazos directos entre sí. El primero no es un error en absoluto, sino solo una forma de detener el script y generar información de depuración para que pueda analizarla manualmente. El segundo no es un error per se, pero se convertirá en un error si no lo detecta. El último está desencadenando un error real en el motor PHP que se manejará de acuerdo con la configuración de su entorno PHP (en algunos casos se muestra al usuario, en otros casos simplemente se registra en un archivo o no se guarda).

Emil Vikström
fuente
1
¿Qué sucede cuando se lanza una excepción pero no se detecta? Causará un error fatal, supongo. Y con lo trigger_error()mismo pasa. entonces cual es la diferencia?
CuriousMind
4
La diferencia es que puede detectar la excepción y manejarla de la forma que desee.
Emil Vikström