Come ottenere la sequenza di esecuzione degli hooks/actions di WordPress?

29 set 2014, 10:59:23
Visualizzazioni: 58.6K
Voti: 67

In che ordine vengono eseguiti gli hook di add_action?

ad esempio:

init
wp_head
wp_footer
after_theme_setup 
ecc...
???
???
???



MODIFICA:

Ho pubblicato anche la mia soluzione.

1
Commenti

nota, i dati di BACK-END e FRONT-END differiscono

T.Todua T.Todua
4 ott 2024 20:45:24
Tutte le risposte alla domanda 6
13
123

"Dati! Dati! Dati!" gridò impazientemente. "Non posso fare mattoni senza argilla."

Sherlock Holmes - L'avventura dei faggi ramati

Quindi raccogliamo alcuni dati reali da un'installazione pulita di WordPress 5.7.2 con il tema TwentyTwelve attivato e solo un singolo widget di testo.

Per la pagina home, vengono effettuate le seguenti chiamate do_action / do_action_ref_array nell'ordine indicato (utente disconnesso):

[0] => mu_plugin_loaded
[1] => muplugins_loaded
[2] => registered_taxonomy
[3] => registered_taxonomy
[4] => registered_taxonomy
[5] => registered_taxonomy
[6] => registered_taxonomy
[7] => registered_post_type
[8] => registered_post_type
[9] => registered_post_type
[10] => registered_post_type
[11] => registered_post_type
[12] => registered_post_type
[13] => registered_post_type
[14] => registered_post_type
[15] => registered_post_type
[16] => registered_post_type
[17] => plugins_loaded
[18] => sanitize_comment_cookies
[19] => wp_roles_init
[20] => setup_theme
[21] => unload_textdomain
[22] => load_textdomain
[23] => after_setup_theme
[24] => load_textdomain
[25] => load_textdomain
[26] => auth_cookie_malformed
[27] => set_current_user
[28] => init
[29] => registered_post_type
[30] => registered_post_type
[31] => registered_post_type
[32] => registered_post_type
[33] => registered_post_type
[34] => registered_post_type
[35] => registered_post_type
[36] => registered_post_type
[37] => registered_post_type
[38] => registered_post_type
[39] => registered_taxonomy
[40] => registered_taxonomy
[41] => registered_taxonomy
[42] => registered_taxonomy
[43] => registered_taxonomy
[44] => widgets_init
[45] => register_sidebar
[46] => register_sidebar
[47] => register_sidebar
[48] => wp_register_sidebar_widget
[49] => wp_register_sidebar_widget
[50] => wp_register_sidebar_widget
[51] => wp_register_sidebar_widget
[52] => wp_register_sidebar_widget
[53] => wp_register_sidebar_widget
[54] => wp_register_sidebar_widget
[55] => wp_register_sidebar_widget
[56] => wp_register_sidebar_widget
[57] => wp_register_sidebar_widget
[58] => wp_register_sidebar_widget
[59] => wp_register_sidebar_widget
[60] => wp_register_sidebar_widget
[61] => wp_register_sidebar_widget
[62] => wp_register_sidebar_widget
[63] => wp_register_sidebar_widget
[64] => wp_default_scripts
[65] => wp_register_sidebar_widget
[66] => wp_register_sidebar_widget
[67] => wp_register_sidebar_widget
[68] => wp_register_sidebar_widget
[69] => wp_register_sidebar_widget
[70] => wp_register_sidebar_widget
[71] => wp_register_sidebar_widget
[72] => wp_register_sidebar_widget
[73] => wp_register_sidebar_widget
[74] => wp_register_sidebar_widget
[75] => wp_register_sidebar_widget
[76] => wp_register_sidebar_widget
[77] => wp_register_sidebar_widget
[78] => wp_register_sidebar_widget
[79] => wp_register_sidebar_widget
[80] => wp_register_sidebar_widget
[81] => wp_register_sidebar_widget
[82] => wp_register_sidebar_widget
[83] => wp_register_sidebar_widget
[84] => wp_register_sidebar_widget
[85] => wp_register_sidebar_widget
[86] => wp_register_sidebar_widget
[87] => wp_register_sidebar_widget
[88] => wp_register_sidebar_widget
[89] => wp_register_sidebar_widget
[90] => wp_register_sidebar_widget
[91] => wp_register_sidebar_widget
[92] => wp_register_sidebar_widget
[93] => wp_register_sidebar_widget
[94] => wp_sitemaps_init
[95] => wp_loaded
[96] => parse_request
[97] => send_headers
[98] => parse_tax_query
[99] => parse_query
[100] => pre_get_posts
[101] => posts_selection
[102] => wp
[103] => template_redirect
[104] => get_header
[105] => wp_head
[106] => wp_enqueue_scripts
[107] => wp_default_styles
[108] => enqueue_block_assets
[109] => wp_print_styles
[110] => wp_print_scripts
[111] => wp_body_open
[112] => parse_tax_query
[113] => parse_query
[114] => pre_get_posts
[115] => parse_tax_query
[116] => posts_selection
[117] => parse_tax_query
[118] => parse_query
[119] => pre_get_posts
[120] => parse_tax_query
[121] => posts_selection
[122] => parse_tax_query
[123] => parse_query
[124] => pre_get_posts
[125] => parse_tax_query
[126] => posts_selection
[127] => parse_tax_query
[128] => parse_query
[129] => pre_get_posts
[130] => parse_tax_query
[131] => posts_selection
[132] => parse_term_query
[133] => pre_get_terms
[134] => loop_start
[135] => the_post
[136] => get_template_part_content
[137] => get_template_part
[138] => parse_comment_query
[139] => pre_get_comments
[140] => parse_comment_query
[141] => pre_get_comments
[142] => comment_form_comments_closed
[143] => loop_end
[144] => get_sidebar
[145] => dynamic_sidebar_before
[146] => dynamic_sidebar
[147] => dynamic_sidebar_after
[148] => get_footer
[149] => twentytwelve_credits
[150] => wp_footer
[151] => wp_print_footer_scripts
[152] => shutdown

utilizzando il plugin must-use:

add_action( 'all', function ( $tag ) {
    static $hooks = array();
    // Solo hook do_action / do_action_ref_array
    if ( did_action( $tag ) ) {
        $hooks[] = $tag;
    }
    if ( 'shutdown' === $tag ) {
        print_r( $hooks );
    }
} );

che stampa gli hook di azione raccolti, per la pagina corrente, nell'ultima azione disponibile del core (shutdown).

Se vuoi verificare l'ordine delle azioni e quante volte ciascuna viene attivata, puoi usare ad esempio:

add_action ( 'shutdown', function(){
    print_r ( $GLOBALS['wp_actions'] );         
} );

o senza globals espliciti:

add_action ( 'shutdown', function() use ( &$wp_actions ) {
    print_r ( $wp_actions );      
} );

che restituisce l'array:

[mu_plugin_loaded] => 1
[muplugins_loaded] => 1
[registered_taxonomy] => 10
[registered_post_type] => 20
[plugins_loaded] => 1
[sanitize_comment_cookies] => 1
[wp_roles_init] => 1
[setup_theme] => 1
[unload_textdomain] => 1
[load_textdomain] => 3
[after_setup_theme] => 1
[auth_cookie_malformed] => 1
[set_current_user] => 1
[init] => 1
[widgets_init] => 1
[register_sidebar] => 3
[wp_register_sidebar_widget] => 45
[wp_default_scripts] => 1
[wp_sitemaps_init] => 1
[wp_loaded] => 1
[parse_request] => 1
[send_headers] => 1
[parse_tax_query] => 9
[parse_query] => 5
[pre_get_posts] => 5
[posts_selection] => 5
[wp] => 1
[template_redirect] => 1
[get_header] => 1
[wp_head] => 1
[wp_enqueue_scripts] => 1
[wp_default_styles] => 1
[enqueue_block_assets] => 1
[wp_print_styles] => 1
[wp_print_scripts] => 1
[wp_body_open] => 1
[parse_term_query] => 1
[pre_get_terms] => 1
[loop_start] => 1
[the_post] => 1
[get_template_part_content] => 1
[get_template_part] => 1
[parse_comment_query] => 2
[pre_get_comments] => 2
[comment_form_comments_closed] => 1
[loop_end] => 1
[get_sidebar] => 1
[dynamic_sidebar_before] => 1
[dynamic_sidebar] => 1
[dynamic_sidebar_after] => 1
[get_footer] => 1
[twentytwelve_credits] => 1
[wp_footer] => 1
[wp_print_footer_scripts] => 1
[shutdown] => 1

dove possiamo ottenere il conteggio totale con echo array_sum( $GLOBALS['wp_actions'] );

Ecco una versione formattata:

add_action ( 'shutdown', function() {
    foreach ( $GLOBALS['wp_actions'] as $action => $count ) {
        printf( '%s (%d) <br/>' . PHP_EOL, $action, $count );
    }
} );

o senza globals espliciti:

add_action ( 'shutdown', function() use ( &$wp_actions ) {
    foreach ( $wp_actions as $action => $count ) {
        printf( '%s (%d) <br/>' . PHP_EOL, $action, $count );
    }
} );

per ottenere la seguente lista:

mu_plugin_loaded (1)
muplugins_loaded (1)
registered_taxonomy (10)
registered_post_type (20)
plugins_loaded (1)
sanitize_comment_cookies (1)
wp_roles_init (1)
setup_theme (1)
unload_textdomain (1)
load_textdomain (3)
after_setup_theme (1)
auth_cookie_malformed (1)
set_current_user (1)
init (1)
widgets_init (1)
register_sidebar (3)
wp_register_sidebar_widget (45)
wp_default_scripts (1)
wp_sitemaps_init (1)
wp_loaded (1)
update_option (1)
update_option__transient_doing_cron (1)
updated_option (1)
set_transient_doing_cron (1)
setted_transient (1)
requests-requests.before_request (1)
requests-curl.before_request (1)
http_api_curl (1)
requests-curl.before_send (1)
requests-curl.after_send (1)
requests-curl.after_request (1)
requests-requests.before_parse (1)
http_api_debug (1)
parse_request (1)
send_headers (1)
parse_tax_query (9)
parse_query (5)
pre_get_posts (5)
posts_selection (5)
wp (1)
template_redirect (1)
get_header (1)
wp_head (1)
wp_enqueue_scripts (1)
wp_default_styles (1)
enqueue_block_assets (1)
wp_print_styles (1)
wp_print_scripts (1)
wp_body_open (1)
parse_term_query (1)
pre_get_terms (1)
loop_start (1)
the_post (1)
get_template_part_content (1)
get_template_part (1)
parse_comment_query (2)
pre_get_comments (2)
comment_form_comments_closed (1)
loop_end (1)
get_sidebar (1)
dynamic_sidebar_before (1)
dynamic_sidebar (1)
dynamic_sidebar_after (1)
get_footer (1)
twentytwelve_credits (1)
wp_footer (1)
wp_print_footer_scripts (1)
shutdown (1)

PS: Dovresti anche dare un'occhiata all'ottimo plugin Query Monitor di John Blackbourn. (Non sono collegato a questo plugin)

29 set 2014 12:04:02
Commenti

Davvero molto bello!

jdm2112 jdm2112
19 mar 2015 21:30:32

Grazie per aver menzionato Query Monitor. Sembra essere un plugin utile in questo caso.

D.A.H D.A.H
16 ott 2015 12:53:37

@kraftner grazie per l'aggiornamento, avevo sempre pianificato (ma poi me ne sono dimenticato) di linkare direttamente alla storia stessa come fonte appropriata, ovviamente le mie capacità da Sherlock Holmes nella ricerca non erano eccezionali in quel momento ;-)

birgire birgire
1 mar 2017 15:22:07

Mi è piaciuta la citazione e volevo vedere più contesto. E dato che avevo già il link per me stesso, perché non aggiornarlo anche qui. :)

kraftner kraftner
1 mar 2017 16:22:28

Questo dovrebbe far parte del codex, sono serio.

Johansson Johansson
13 lug 2017 19:54:45

felice di sentire che ti sia utile @JackJohansson

birgire birgire
13 lug 2017 21:22:13

Post di oltre 4 anni fa e ancora utile. Grazie mille!

Sebastian Kaczmarek Sebastian Kaczmarek
5 feb 2019 12:15:21

Questo in realtà non ottiene la sequenza esatta a causa del raggruppamento per nome dell'hook.

Walf Walf
12 lug 2021 06:28:28

@Walf Per favore guarda la risposta aggiornata per WP 5.7.2 e il mu-plugin.

birgire birgire
12 lug 2021 13:49:56

La tua risposta aggiornata è un miglioramento significativo. Tuttavia, potrebbe non produrre alcun output se un errore interrompe l'esecuzione. Certo, un errore ti dice dove è avvenuto, ma conoscere gli eventi precedenti può essere estremamente utile. Inoltre, l'uso di istruzioni print/dump potrebbe interferire con la richiesta o essere annullato del tutto se si termina la richiesta in anticipo.

Walf Walf
13 lug 2021 04:35:37

WordPress registra l'hook di shutdown come una funzione di shutdown con PHP register_shutdown_function( 'shutdown_action_hook' ), quindi verrà eseguito alla fine anche se, ad esempio, la callback di un altro hook chiama exit(), genera un errore con trigger_error() o lancia un Error non catturato. Secondo un commento nella documentazione PHP, dovrebbe essere eseguito anche dopo un timeout. Sì, non verrà visualizzato se fastcgi_finish_request lo interrompe, ma penso che si potrebbe registrarlo nel log se la stampa è un problema.

birgire birgire
13 lug 2021 15:06:28

Ancora utile nel 2022: grazie!

Gas Gas
29 set 2022 12:50:15

Felice di sapere che è ancora utile @Gas

birgire birgire
29 set 2022 14:00:56
Mostra i restanti 8 commenti
3
28

Ecco il grafico di carico di WordPress

Grafico di Carico WordPress

Fonte di @Rarst

29 set 2014 11:04:06
Commenti

Aggiungi almeno la fonte, o ancora meglio: trova un duplicato per questa domanda.

fuxia fuxia
29 set 2014 11:36:59

In realtà non sapevo da dove l'avevo presa. Avevo questa immagine salvata sul mio PC. Altrimenti l'avrei fatto.

Robert hue Robert hue
29 set 2014 11:43:44

È anche pubblicata sulla homepage di Tom Mc Farlin: The WordPress Page Lifecycle -> https://tommcfarlin.com/wordpress-page-lifecycle/

D.A.H D.A.H
16 ott 2015 13:05:24
0

Soluzione Trovata!

Grazie @birgire per la risposta utile. Aggiungo che muplugins_loaded a volte non viene attivato, quindi utilizzerò plugins_loaded come hook più precoce (ma a quel punto, l'autorizzazione dell'utente non è ancora avvenuta. Se vuoi verificare l'autorizzazione dell'utente, allora init è il più precoce per quello)...

p.s. esistono plugin eccellenti:

1) Query Monitor - Puoi vedere tutto ciò che accade durante il caricamento della pagina, ad esempio la durata di ogni funzione eseguita e molto altro (visualizza tutti gli screenshot nella pagina del plugin):

Schermata di esempio di Query Monitor che mostra le statistiche di caricamento

2) WP-DEBUG-BAR + WP-DEBUG-SLOW-ACTIONS:
a) lista dei debug hook (azioni) eseguiti sul tuo sito.
b) Visualizza la durata di ogni azione (non funzione): Schermata di esempio di WP-DEBUG-BAR che mostra le azioni e i tempi

23 dic 2017 22:22:50
0

La sequenza di base può essere trovata anche nella documentazione ufficiale:

https://codex.wordpress.org/Plugin_API/Action_Reference

28 mag 2018 17:57:16
0

Questa soluzione è simile alla risposta di @birgire, ma fornisce un report dettagliato che può essere visualizzato per qualsiasi URL in un sito WordPress. Dovrai essere loggato come utente di livello Amministratore, quindi aggiungere ?wp-hooks alla fine dell'URL che vuoi testare.

/**
* Riferimento agli Hook di WordPress
*
* Mostra tutti gli hook di azione e filtro in fondo a qualsiasi pagina
* aggiungendo ?wp-hooks alla fine dell'URL quando si è loggati
* come utente di livello Amministratore.
*/
function kevinlearynet_hooks_reference() {

    // Mostrato solo per utenti di livello Amministratore quando ?list-wp-hooks è aggiunto all'URL
    $trigger = isset( $_GET['wp-hooks'] ) && current_user_can( 'manage_options' );
    if ( ! $trigger ) return;

    // Acquisisce e ordina filtri e hook
    $filters = array_keys( $GLOBALS['wp_filter'] );
    sort( $filters );
    $actions = array_keys( $GLOBALS['wp_actions'] );

    // Output del template
    ob_start();
    ?>
    <section class="wp-hooks">
    <h1 class="wp-hooks__h1">Riferimento agli Hook di WordPress</h1>
    <div class="wp-hooks__lists">
    <div class="wp-hooks__col">
    <h2 class="wp-hooks__h2">Azioni</h2>
    <?php foreach ( $actions as $hook ) : ?>
    <p class="wp-hooks__hook"><?php echo $hook; ?></p>
    <?php endforeach; ?>
    </div>
    <div class="wp-hooks__col">
    <h2 class="wp-hooks__h2">Filtri</h2>
    <?php foreach ( $filters as $hook ) : ?>
    <p class="wp-hooks__hook"><?php echo $hook; ?></p>
    <?php endforeach; ?>
    </div>
    </div>
    </section>
    <style>
    .wp-hooks {
        padding: 30px;
        margin: 30px;
        border-radius: 4px;
        background: white;
        font-size: 16px;
        line-height: 1.4;
        height: 50vh;
        min-height: 500px;
        overflow-y: scroll;
    }
    .wp-hooks__lists {
        display: flex;
    }
    .wp-hooks__col {
        flex: 1;
        width: 50%;
    }
    .wp-hooks__h1 {
        margin: 0 0 20px;
    }
    .wp-hooks__h2 {
        line-height: 1;
        font-size: 18px;
        margin: 0 0 10px;
    }
    .wp-hooks__hook {
        padding: 0;
        margin: 0;
    }
    </style>
    <?php
    ob_end_flush();
}
add_action( 'shutdown', 'kevinlearynet_hooks_reference' );

L'output sarà simile a questo:

Anteprima dell'output degli hook

Ho scritto questo codice personalmente, quindi ecco la fonte originale per riferimento. Include maggiori dettagli sulle decisioni relative all'ordinamento e alla funzionalità.

5 mag 2020 18:44:11
0

Nessuna due richieste sono esattamente uguali. Un modo rapido e sporco ma molto accurato per scoprire cosa sta succedendo è temporaneamente aggiungere righe all'inizio delle funzioni do_action e do_action_ref_array in wp-includes/plugin.php per registrare ogni hook, ad esempio:

if (isset($some_trigger_from_get_post_head_etc)) file_put_contents(ABSPATH . 'hooks.log', "$hook_name\n", FILE_APPEND);

Potresti voler fare lo stesso per le funzioni apply_filters e apply_filters_ref_array nello stesso file. Non ho trovato un modo migliore per ottenere la sequenza completa e cronologica, inclusi gli hook che si attivano prima ancora che i plugin must-use vengano caricati e dopo shutdown.

24 nov 2017 10:48:48