Capturar Excepciones Propias en WordPress
Estoy construyendo un paquete con mis propias Excepciones pero cuando intento capturar una excepción obtengo un error fatal: Uncaught exception. Esta situación solo ocurre cuando el método que lanza la excepción se pasa mediante add_action( 'init', array( $this, 'wp_some_method' ) );
Ejemplo:
class SomeClass {
public function __construct() {
add_action( 'init', array( $this, 'wp_some_method' ) );
echo '__constructor<br />';
}
function some_method(){
throw new \Exception('algún mensaje');
}
function wp_some_method( $post_type ){
throw new \Exception('Algún segundo error');
}
}
try{
echo 'try <br />';
$o = new SomeClass();
//$o->some_method(); - esto lanza la excepción correctamente
} catch (\Exception $ex) {
echo $ex->getMessage();
}
Se muestra en pantalla:
try
__constructor
Y: Fatal error: Uncaught exception 'Exception'

Tu excepción no es capturada por el bloque try{} catch(){}, porque no se lanza dentro del bloque try catch. Esto demuestra una falta de comprensión de los eventos asíncronos y del sistema de hooks/acciones/eventos de WordPress.
Los métodos de tu objeto están vinculados al hook de acción init, y se lanzan cuando se activa el hook init, no cuando se crea el objeto, y no cuando se vinculan.
Por ejemplo:
class SomeClass {
public function __construct() {
// cuando ocurre la acción/evento init, llama a wp_some_method
add_action( 'init', array( $this, 'wp_some_method' ) );
}
function wp_some_method( $post_type ){
throw new \Exception('error');
}
}
try{
// genial, no se lanzaron excepciones al crear el objeto
$o = new SomeClass();
} catch (\Exception $ex) {
echo $ex->getMessage();
}
// un pequeño periodo de tiempo después, en algún lugar de WP Core...
do_action( 'init' ); // ¡un método que vinculamos al hook init lanzó una excepción, pero no había nada para capturarla!
Tu método no se llama cuando se crea tu objeto. Se vincula al evento init, sí, pero no se llama, precisamente porque el evento 'init' aún no ha ocurrido. El evento init ocurre mucho después de que se ejecute tu sentencia try{} catch.
Así que en su lugar, estos enfoques serían más apropiados:
- Añadir un try catch en los métodos de la clase (mejor opción)
- No lanzar excepciones en funciones vinculadas a hooks/eventos (aún mejor)
- Lanzar la excepción en un nuevo método que no sea el que has vinculado, para poder añadir un try catch (aceptable, requiere buena separación de responsabilidades y abstracción)
- Añadir un manejador global de errores (poco elegante, no recomendado, tomará más tiempo del que vale, podría capturar otras excepciones que no pretendías capturar)
De lo contrario, no hay ninguna razón racional, lógica o de sentido común por la que la línea de código que dice throw new \Exception
debería ejecutarse dentro del bloque try catch como tienes arriba, a menos que la llames manualmente como hiciste en tu prueba.
