Come ottenere la sequenza di esecuzione degli hooks/actions di WordPress?
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.

"Dati! Dati! Dati!" gridò impazientemente. "Non posso fare mattoni senza argilla."
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)

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

@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 ;-)

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

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

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

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.

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.


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

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

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

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):
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):

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

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:
Ho scritto questo codice personalmente, quindi ecco la fonte originale per riferimento. Include maggiori dettagli sulle decisioni relative all'ordinamento e alla funzionalità.

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
.
