Cum să obții secvența de execuție a hook-urilor/acțiunilor din WordPress?
În ce ordine se execută hook-urile add_action
?
de exemplu:
init
wp_head
wp_footer
after_theme_setup
etc...
???
???
???
EDIT:
Mi-am postat și soluția.

"Date! Date! Date!" strigă el nerăbdător. "Nu pot face cărămizi fără argilă."
Așadar, hai să adunăm niște date reale de la o instalare standard WordPress 5.7.2 cu tema TwentyTwelve activată și un singur widget Text.
Pentru pagina principală, următoarele apeluri do_action / do_action_ref_array
sunt efectuate în următoarea ordine (utilizator deconectat):
[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
folosind plugin-ul must-use:
add_action( 'all', function ( $tag ) {
static $hooks = array();
// Doar hook-uri do_action / do_action_ref_array.
if ( did_action( $tag ) ) {
$hooks[] = $tag;
}
if ( 'shutdown' === $tag ) {
print_r( $hooks );
}
} );
care afișează hook-urile de acțiune colectate, pentru pagina curentă, în ultima acțiune disponibilă din nucleu (shutdown).
Dacă doriți să verificați ordinea acțiunilor și de câte ori este declanșată fiecare, puteți folosi de exemplu:
add_action ( 'shutdown', function(){
print_r ( $GLOBALS['wp_actions'] );
} );
sau fără globals explicite:
add_action ( 'shutdown', function() use ( &$wp_actions ) {
print_r ( $wp_actions );
} );
care afișează array-ul:
[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
unde putem obține numărul total cu echo array_sum( $GLOBALS['wp_actions'] );
Iată o versiune mai frumoasă:
add_action ( 'shutdown', function() {
foreach ( $GLOBALS['wp_actions'] as $action => $count ) {
printf( '%s (%d) <br/>' . PHP_EOL, $action, $count );
}
} );
sau fără globals explicite:
add_action ( 'shutdown', function() use ( &$wp_actions ) {
foreach ( $wp_actions as $action => $count ) {
printf( '%s (%d) <br/>' . PHP_EOL, $action, $count );
}
} );
pentru a obține următoarea listă:
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: Ar trebui să verificați și minunatul plugin Query Monitor de John Blackbourn. (Nu sunt asociat cu acest plugin)

Mulțumesc că ai menționat Query Monitor. Pare a fi un plugin util în acest caz.

@kraftner mulțumesc pentru actualizare, întotdeauna am plănuit (dar am uitat) să fac legătura directă către povestea în sine ca sursă corectă, evident că abilitățile mele de detectiv Sherlock Holmes nu au fost grozave atunci ;-)

Mi-a plăcut citatul și am vrut să văd mai mult context. Și cum deja aveam linkul pentru mine, de ce să nu-l actualizez și aici. :)

Aceasta nu obține exact secvența din cauza grupării după numele hook-ului.

@Walf Te rog să consulți răspunsul actualizat pentru WP 5.7.2 și mu-plugin.

Răspunsul tău actualizat este o îmbunătățire semnificativă. Cu toate acestea, este posibil să nu producă nicio ieșire dacă o eroare oprește execuția. Desigur, o eroare îți spune unde a avut loc, dar cunoașterea evenimentelor precedente poate fi extrem de utilă. De asemenea, utilizarea instrucțiunilor print/dump este probabil să interfereze cu cererea sau să fie anulată complet dacă se termină cererea prematur.

WordPress înregistrează cârligul (hook) de acțiune shutdown ca o funcție de închidere cu PHP register_shutdown_function( 'shutdown_action_hook' )
, astfel încât va rula la final chiar dacă, de exemplu, un alt cârlig apelează exit()
, declanșează o eroare cu trigger_error()
sau aruncă o eroare neprinsă. Conform comentariilor din documentația PHP, ar trebui să ruleze și după expirarea timpului. Da, nu va afișa dacă fastcgi_finish_request o întrerupe, dar cred că s-ar putea înregistra în jurnal dacă afișarea este o problemă.


Adaugă cel puțin sursa, sau chiar mai bine: găsește o întrebare duplicat pentru aceasta.

De fapt, nu știam de unde am obținut-o. Aveam această imagine salvată pe PC. Altfel aș fi făcut asta.

Este publicată și pe pagina principală a lui Tom Mc Farlin: The WordPress Page Lifecycle -> https://tommcfarlin.com/wordpress-page-lifecycle/

Soluție găsită!
Mulțumesc @birgire pentru răspunsul frumos. Voi adăuga că muplugins_loaded
uneori nu se declanșează, așa că voi folosi plugins_loaded
ca primul hook (dar în acel moment, autorizarea utilizatorului nu este încă făcută. Dacă doriți să verificați autorizarea utilizatorului, atunci init
este cel mai devreme pentru asta)...
p.s. există plugin-uri excelente:
1) Query Monitor - Puteți vedea tot ce se întâmplă la încărcarea paginii, adică durata fiecărei funcții executate și multe altele (vizualizați toate capturile de ecran pe pagina plugin-ului):
2) WP-DEBUG-BAR + WP-DEBUG-SLOW-ACTIONS:
a) listă de depanare a hook-urilor (acțiuni) rulate pe site-ul tău.
b) Vezi durata fiecărei acțiuni (nu funcție):

Secvența de bază poate fi găsită și în documentația oficială:

Acest lucru este similar cu răspunsul lui @birgire, dar oferă un raport detaliat care poate fi afișat pentru orice URL într-un site WordPress. Va trebui să fii autentificat ca utilizator cu nivel de Administrator, apoi adaugă ?wp-hooks
la sfârșitul URL-ului pe care dorești să-l testezi.
/**
* Referință pentru Hook-uri WordPress
*
* Afișează toate hook-urile de acțiune și filtrare în partea de jos a oricărei pagini
* prin adăugarea parametrului ?wp-hooks la URL cât timp ești autentificat
* ca utilizator cu nivel de Administrator.
*/
function kevinlearynet_hooks_reference() {
// Se afișează doar pentru administratori când se adaugă ?wp-hooks la URL
$trigger = isset( $_GET['wp-hooks'] ) && current_user_can( 'manage_options' );
if ( ! $trigger ) return;
// Captură și sortează filtrele și hook-urile
$filters = array_keys( $GLOBALS['wp_filter'] );
sort( $filters );
$actions = array_keys( $GLOBALS['wp_actions'] );
// Generează șablonul de afișare
ob_start();
?>
<section class="wp-hooks">
<h1 class="wp-hooks__h1">Referință Hook-uri WordPress</h1>
<div class="wp-hooks__lists">
<div class="wp-hooks__col">
<h2 class="wp-hooks__h2">Acțiuni</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">Filtre</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' );
Ieșirea arată astfel:
Am scris despre asta pe blogul meu, așa că iată sursa originală pentru referință. Aceasta include mai multe detalii despre deciziile din spatele sortării și funcționalității.

Nu există două cereri exact la fel.
O metodă rapidă și simplă, dar foarte precisă pentru a afla ce se întâmplă, este să adăugați temporar linii la începutul funcțiilor do_action
și do_action_ref_array
din wp-includes/plugin.php
pentru a înregistra fiecare hook, de exemplu:
if (isset($some_trigger_from_get_post_head_etc)) file_put_contents(ABSPATH . 'hooks.log', "$hook_name\n", FILE_APPEND);
Ați putea face același lucru și pentru funcțiile apply_filters
și apply_filters_ref_array
din același fișier.
Nu am găsit o metodă mai bună pentru a obține secvența completă și cronologică, inclusiv hook-urile care se declanșează înainte ca plugin-urile must-use să se încarce și după shutdown
.
