Tengo la intención de brindarles una discusión inusual sobre el control de errores.
Construí un muy buen controlador de errores en un lenguaje hace años, y aunque algunos de los nombres han cambiado, los principios del procesamiento de errores son los mismos hoy. Tenía un sistema operativo multitarea personalizado y tenía que poder recuperarme de errores de datos en todos los niveles sin fugas de memoria, crecimiento de pila o bloqueos. Entonces, lo que sigue es mi comprensión de cómo deben operar los errores y las excepciones y en qué se diferencian. Solo diré que no entiendo cómo funciona el funcionamiento interno de try catch, así que supongo que hasta cierto punto.
Lo primero que sucede bajo las cubiertas para el procesamiento de errores es saltar de un estado de programa a otro. ¿Cómo se hace eso? Llegaré a eso.
Históricamente, los errores son más antiguos y simples, y las excepciones son más nuevas y un poco más complejas y capaces. Los errores funcionan bien hasta que necesita hacerlos burbujear, lo que equivale a entregar un problema difícil a su supervisor.
Los errores pueden ser números, como números de error y, a veces, con una o más cadenas asociadas. Por ejemplo, si se produce un error de lectura de archivo, es posible que pueda informar qué es y posiblemente fallar correctamente. (Hay, es un paso adelante de simplemente chocar como en los viejos tiempos).
Lo que no se dice a menudo sobre las excepciones es que las excepciones son objetos en capas en una pila de excepciones especial. Es como una pila de retorno para el flujo del programa, pero tiene un estado de retorno solo para intentos y capturas de errores. (Solía llamarlos ePush y ePop, y? Abort era un lanzamiento condicional que haría ePop y se recuperaría a ese nivel, mientras que Abort era un dado completo o una salida).
En la parte inferior de la pila está la información sobre el llamador inicial, el objeto que conoce el estado cuando se inició el intento externo, que suele ser cuando se inició el programa. Encima de eso, o la siguiente capa en la pila, con arriba siendo los niños y abajo los padres, es el objeto de excepción del siguiente bloque interno try / catch.
Si pones un intento dentro de un intento, estás apilando el intento interior encima del intento exterior. Cuando ocurre un error en el intento interno y la captura interna no puede manejarlo o el error se lanza al intento externo, entonces el control se pasa al bloque de captura externo (objeto) para ver si puede manejar el error, es decir su supervisor.
Entonces, lo que realmente hace esta pila de errores es poder marcar y restaurar el flujo del programa y el estado del sistema, en otras palabras, permite que un programa no bloquee la pila de devolución y arruine las cosas para otros (datos) cuando las cosas van mal. Por lo tanto, también guarda el estado de cualquier otro recurso, como los grupos de asignación de memoria, y puede limpiarlos cuando se realiza la captura. En general, esto puede ser algo muy complicado y es por eso que el manejo de excepciones suele ser lento. En general, es necesario que haya bastante estado en estos bloques de excepción.
Entonces, un bloque try / catch establece un estado al que poder regresar si todo lo demás se estropea. Es como un padre. Cuando nuestras vidas se estropean, podemos volver a caer en el regazo de nuestros padres y ellos lo arreglarán nuevamente.
Espero no haberte decepcionado.
Errors are generally unrecoverable
<- en realidad, esto no es realmente cierto.E_ERROR
yE_PARSE
son los dos errores irrecuperables más comunes (hay un par de otros) pero la gran mayoría de los errores que verá en dev son recuperables (E_NOTICE
,E_WARNING
et al). Desafortunadamente, el manejo de errores de PHP es un completo desastre: todo tipo de cosas desencadenan errores innecesariamente (la gran mayoría de las funciones del sistema de archivos, por ejemplo). En general, las excepciones son "la forma de OOP", pero desafortunadamente algunas de las API de OOP nativas de PHP usan errores en lugar de excepciones :-(