Cum să prindeți propriile Excepții în WordPress

6 mar. 2014, 19:40:18
Vizualizări: 13.6K
Voturi: 3

Am construit un pachet cu propria mea Excepție, dar când încerc să prind o excepție primesc eroare fatală: Uncaught exception. Această situație apare doar când metoda care aruncă excepția este apelată prin add_action( 'init', array( $this, 'wp_some_method' ) ); Exemplu:

class SomeClass {
    public function __construct() {
        add_action( 'init', array( $this, 'wp_some_method' ) );
        echo '__constructor<br />';
    }
    function some_method(){
        throw new \Exception('mesaj de eroare');
    }
    function wp_some_method( $post_type ){
        throw new \Exception('O altă eroare'); 
    }
}
try{
    echo 'try <br />';
    $o = new SomeClass();
    //$o->some_method(); - acest apel aruncă excepția corect

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

Se afișează pe ecran:

try

__constructor

Și: Fatal error: Uncaught exception 'Exception'

2
Comentarii

Când excepția ta este aruncată, clasa a fost deja creată și blocul try a avut deja loc și s-a încheiat. Cel mai bun mod de a demonstra acest lucru este să adaugi un comentariu după instrucțiunea try catch care spune // hook-ul init nu a fost încă declanșat

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

Am editat postarea mea. Dar nu înțeleg răspunsul tău.

Michał Kalkowski Michał Kalkowski
6 mar. 2014 21:52:27
Toate răspunsurile la întrebare 1
0

Excepția ta nu este prinsă de blocul try{} catch(){}, deoarece nu este aruncată în interiorul acestuia. Aceasta demonstrează o lipsă de înțelegere a evenimentelor asincrone și a sistemului de hook-uri/acțiuni/evenimente din WordPress.

Metodele obiectului tău sunt atașate la hook-ul de acțiune init și sunt aruncate atunci când hook-ul init este declanșat, nu atunci când obiectul este creat și nu atunci când sunt atașate.

Exemplu:

class SomeClass {
    public function __construct() {
        // când acțiunea/evenimentul init are loc, apelează wp_some_method
        add_action( 'init', array( $this, 'wp_some_method' ) );
    }
    function wp_some_method( $post_type ){
        throw new \Exception('eroare'); 
    }
}
try{
    // perfect, nu s-au aruncat excepții la crearea obiectului
    $o = new SomeClass();    
} catch (\Exception $ex) {
    echo $ex->getMessage();
}

// după o perioadă scurtă de timp, undeva în WP Core...

do_action( 'init' ); // o metodă atașată la hook-ul init a aruncat o excepție, dar nimic nu a fost acolo să o prindă!

Metoda ta nu este apelată atunci când obiectul este creat. Ea este atașată la evenimentul init, dar nu este apelată, tocmai pentru că evenimentul 'init' nu a avut loc încă. Evenimentul init are loc mult după ce blocul try{} catch rulează.

Deci, în schimb, aceste abordări ar fi mai potrivite:

  • adaugă un try catch în metodele clasei (cea mai bună variantă)
  • Nu arunca excepții în funcțiile atașate la hook-uri/evenimente (și mai bine)
  • aruncă excepția într-o metodă nouă care nu este metoda pe care ai atașat-o, astfel încât să poți adăuga un try catch (acceptabil, necesită o bună separare a preocupărilor și abstractizare)
  • adaugă un handler global de erori (hackish, nu recomandat, va dura mai mult decât merită, poate prinde alte excepții pe care nu ai intenționat să le prinzi)

Altfel, nu există niciun motiv rațional, logic sau de bun simț pentru care linia de cod care spune throw new \Exception ar trebui să fie executată în interiorul blocului try catch așa cum ai scris mai sus, fără să o apelezi manual cum ai făcut în testul tău.

6 mar. 2014 22:37:50