Gestire le proprie Eccezioni in WordPress

6 mar 2014, 19:40:18
Visualizzazioni: 13.6K
Voti: 3

Ho creato un pacchetto con le mie eccezioni personalizzate, ma quando provo a catturarle ottengo un errore fatale: Uncaught exception. Questo succede solo quando il metodo che lancia l'eccezione viene chiamato tramite add_action( 'init', array( $this, 'wp_some_method' ) ); Esempio:

class SomeClass {
    public function __construct() {
        add_action( 'init', array( $this, 'wp_some_method' ) );
        echo '__constructor<br />';
    }
    function some_method(){
        throw new \Exception('messaggio di errore');
    }
    function wp_some_method( $post_type ){
        throw new \Exception('Secondo errore'); 
    }
}
try{
    echo 'try <br />';
    $o = new SomeClass();
    //$o->some_method(); - qui l'eccezione viene lanciata correttamente

} catch (\Exception $ex) {
    echo $ex->getMessage();
}

Viene visualizzato a schermo:

try

__constructor

E: Fatal error: Uncaught exception 'Exception'

2
Commenti

Quando viene generata la tua eccezione, la classe è già stata creata e il blocco try è già avvenuto e terminato. Il modo migliore per dimostrarlo è aggiungere un commento dopo l'istruzione try catch che dice //the init hook has not been fired yet

Tom J Nowell Tom J Nowell
6 mar 2014 20:03:34

Ho modificato il mio post. Ma non capisco la tua risposta.

Michał Kalkowski Michał Kalkowski
6 mar 2014 21:52:27
Tutte le risposte alla domanda 1
0

La tua eccezione non viene catturata dal blocco try{} catch(){}, perché non viene lanciata all'interno del blocco try catch. Questo dimostra una mancanza di comprensione degli eventi asincroni e del sistema di hook/azioni/eventi di WordPress.

I metodi del tuo oggetto sono collegati all'hook di azione init, e vengono lanciati quando l'hook init viene attivato, non quando l'oggetto viene creato, e non quando vengono collegati.

Esempio:

class SomeClass {
    public function __construct() {
        // quando l'azione/evento init si verifica, chiama wp_some_method
        add_action( 'init', array( $this, 'wp_some_method' ) );
    }
    function wp_some_method( $post_type ){
        throw new \Exception('errore'); 
    }
}
try{
    // bene, nessuna eccezione è stata lanciata durante la creazione dell'oggetto
    $o = new SomeClass();    
} catch (\Exception $ex) {
    echo $ex->getMessage();
}

// un breve periodo di tempo dopo, da qualche parte nel Core di WordPress...

do_action( 'init' ); // un metodo che abbiamo collegato all'hook init ha lanciato un'eccezione, ma non c'era nulla per catturarla!

Il tuo metodo non viene chiamato quando l'oggetto viene creato. È collegato all'evento init sì, ma non viene chiamato, precisamente perché l'evento 'init' non è ancora avvenuto. L'evento init avviene molto tempo dopo che il tuo blocco try{} catch è stato eseguito.

Quindi invece, queste soluzioni sarebbero più appropriate:

  • aggiungi un try catch nei metodi della classe (migliore)
  • Non lanciare eccezioni in funzioni collegate a hook/eventi (ancora meglio)
  • lancia l'eccezione in un nuovo metodo che non sia quello che hai collegato, così puoi aggiungere un try catch (accettabile, richiede una buona separazione delle responsabilità e astrazione)
  • aggiungi un gestore di errori globale (poco elegante, sconsigliato vivamente, richiederà più tempo di quanto valga, potrebbe catturare altre eccezioni che non intendevi catturare)

Altrimenti non c'è alcuna ragione razionale, logica o di buon senso per cui la riga di codice che dice throw new \Exception dovrebbe essere eseguita all'interno del blocco try catch come hai fatto sopra, a meno che tu non la chiami manualmente come hai fatto nel tuo test.

6 mar 2014 22:37:50