Как получить последовательность выполнения хуков/действий WordPress?

29 сент. 2014 г., 10:59:23
Просмотры: 58.6K
Голосов: 67

В каком порядке выполняются хуки add_action?

например:

init
wp_head
wp_footer
after_theme_setup 
и т.д...
???
???
???



РЕДАКТИРОВАТЬ:

Я также опубликовал свое решение.

1
Комментарии

заметка, данные в BACK-END и FRONT-END различаются

T.Todua T.Todua
4 окт. 2024 г. 20:45:24
Все ответы на вопрос 6
13
123

"Данные! Данные! Данные!" — нетерпеливо воскликнул он. "Не могу сделать кирпичи без глины."

Шерлок Холмс - Приключение у Медного Бука

Итак, давайте соберем реальные данные из чистой установки WordPress 5.7.2 с активированной темой TwentyTwelve и всего одним текстовым виджетом.

Для главной страницы выполняются следующие вызовы do_action / do_action_ref_array в указанном порядке (для неавторизованного пользователя):

[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

используя must-use плагин:

add_action( 'all', function ( $tag ) {
    static $hooks = array();
    // Только хуки do_action / do_action_ref_array.
    if ( did_action( $tag ) ) {
        $hooks[] = $tag;
    }
    if ( 'shutdown' === $tag ) {
        print_r( $hooks );
    }
} );

который выводит собранные хуки действий для текущей страницы в последнем доступном действии ядра (shutdown).

Если вы хотите проверить порядок действий и количество их вызовов, можно использовать например:

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

или без явного использования глобальных переменных:

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

что выводит массив:

[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

где мы можем получить общее количество с помощью echo array_sum( $GLOBALS['wp_actions'] );

Вот более читаемая версия:

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

или без явного использования глобальных переменных:

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

чтобы получить следующий список:

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)

P.S.: Также рекомендую отличный плагин Query Monitor от John Blackbourn. (Я не имею отношения к этому плагину)

29 сент. 2014 г. 12:04:02
Комментарии

Очень даже неплохо!

jdm2112 jdm2112
19 мар. 2015 г. 21:30:32

Спасибо, что упомянули Query Monitor. Похоже, в этом случае это полезный плагин.

D.A.H D.A.H
16 окт. 2015 г. 12:53:37

@kraftner спасибо за обновление, я всегда планировал (но забывал об этом) добавить прямую ссылку на саму историю как надёжный источник, очевидно, мои навыки поиска Шерлока Холмса в тот момент были не на высоте ;-)

birgire birgire
1 мар. 2017 г. 15:22:07

Мне понравилась цитата, и я захотел увидеть больше контекста. Раз уж у меня уже была ссылка для себя, почему бы не обновить её и здесь. :)

kraftner kraftner
1 мар. 2017 г. 16:22:28

Это должно быть частью кодекса, я серьёзно.

Johansson Johansson
13 июл. 2017 г. 19:54:45

Рад слышать, что это помогло @JackJohansson

birgire birgire
13 июл. 2017 г. 21:22:13

Запись старше 4 лет, но всё ещё полезна. Большое спасибо!

Sebastian Kaczmarek Sebastian Kaczmarek
5 февр. 2019 г. 12:15:21

Это не даёт точной последовательности из-за группировки по имени хука.

Walf Walf
12 июл. 2021 г. 06:28:28

@Walf Пожалуйста, ознакомьтесь с обновлённым ответом для WP 5.7.2 и mu-плагина.

birgire birgire
12 июл. 2021 г. 13:49:56

Ваш обновленный ответ стал значительно лучше. Однако он может вообще не выводить ничего, если выполнение прервется из-за ошибки. Конечно, ошибка указывает, где она произошла, но знание предшествующих событий может быть крайне полезным. Кроме того, использование операторов print/dump может помешать запросу или вообще не сработать, если запрос завершается досрочно.

Walf Walf
13 июл. 2021 г. 04:35:37

WordPress регистрирует shutdown action hook как shutdown-функцию с помощью PHP register_shutdown_function( 'shutdown_action_hook' ), поэтому она выполнится в конце, даже если, например, callback другого хука вызывает exit(), инициирует ошибку с помощью trigger_error() или выбрасывает неперехваченный Error. Согласно комментарию в документации PHP, она также должна выполняться после таймаута. Да, вывод не отобразится, если fastcgi_finish_request его обрывает, но я думаю, можно залогировать вывод, если печать является проблемой.

birgire birgire
13 июл. 2021 г. 15:06:28

Всё ещё полезно в 2022: спасибо!

Gas Gas
29 сент. 2022 г. 12:50:15

Рад слышать, что это всё ещё полезно, @Gas

birgire birgire
29 сент. 2022 г. 14:00:56
Показать остальные 8 комментариев
3
28

Вот диаграмма загрузки WordPress

Диаграмма загрузки WordPress

Источник: @Rarst

29 сент. 2014 г. 11:04:06
Комментарии

Добавьте хотя бы источник, или еще лучше: найдите дубликат этого вопроса.

fuxia fuxia
29 сент. 2014 г. 11:36:59

Честно говоря, я не знаю, откуда я это взял. У меня это изображение было сохранено на компьютере. В противном случае я бы так и сделал.

Robert hue Robert hue
29 сент. 2014 г. 11:43:44

Это также опубликовано на домашней странице Тома МакФарлина: The WordPress Page Lifecycle -> https://tommcfarlin.com/wordpress-page-lifecycle/

D.A.H D.A.H
16 окт. 2015 г. 13:05:24
0

Решение найдено!

Спасибо @birgire за отличный ответ. Я добавлю к этому, что muplugins_loaded иногда не срабатывает, поэтому я буду использовать plugins_loaded как самый ранний хук (но в этот момент авторизация пользователя еще не выполнена. Если вам нужно проверить авторизацию пользователя, то init - это самый ранний вариант для этого)...

P.S. Существуют отличные плагины:

1) Query Monitor - Вы можете увидеть все, что происходит при загрузке страницы, включая продолжительность выполнения каждой функции и многое другое (посмотрите все скриншоты на странице плагина):

Query Monitor - Скриншот интерфейса

2) WP-DEBUG-BAR + WP-DEBUG-SLOW-ACTIONS:
a) список выполненных хуков (действий) на вашем сайте.
b) Продолжительность каждого действия (не функции): WP-DEBUG-BAR - Скриншот интерфейса

23 дек. 2017 г. 22:22:50
0

Базовую последовательность действий также можно найти в официальной документации:

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

28 мая 2018 г. 17:57:16
0

Это похоже на ответ @birgire, но предоставляет удобный отчет, который можно отобразить для любого URL на сайте WordPress. Вам нужно войти в систему как пользователь с правами администратора, затем добавить ?wp-hooks в конец URL, который вы хотите протестировать.

/**
* Справочник по хукам WordPress
*
* Выводит все хуки действий и фильтров внизу любой страницы
* путем добавления ?wp-hooks к URL, когда вы вошли в систему
* как пользователь с уровнем администратора.
*/
function kevinlearynet_hooks_reference() {

    // Показывается только для пользователей с правами администратора при добавлении ?list-wp-hooks к URL
    $trigger = isset( $_GET['wp-hooks'] ) && current_user_can( 'manage_options' );
    if ( ! $trigger ) return;

    // Сбор и сортировка фильтров и хуков
    $filters = array_keys( $GLOBALS['wp_filter'] );
    sort( $filters );
    $actions = array_keys( $GLOBALS['wp_actions'] );

    // Вывод шаблона
    ob_start();
    ?>
    <section class="wp-hooks">
    <h1 class="wp-hooks__h1">Справочник по хукам WordPress</h1>
    <div class="wp-hooks__lists">
    <div class="wp-hooks__col">
    <h2 class="wp-hooks__h2">Действия</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">Фильтры</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' );

Результат выглядит следующим образом:

Пример вывода справочника по хукам WordPress

Я написал об этом на своем сайте, так что вот оригинальный источник для справки. Там содержится немного больше деталей о решениях, связанных с сортировкой и функциональностью.

5 мая 2020 г. 18:44:11
0

Нет двух абсолютно одинаковых запросов. Быстрый и грязный, но очень точный способ выяснить, что происходит — это временно добавить строки в начало функций do_action и do_action_ref_array в файле wp-includes/plugin.php, чтобы логировать каждый хук, например:

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

Возможно, стоит сделать то же самое для функций apply_filters и apply_filters_ref_array в том же файле. Я не нашел лучшего способа получить полную хронологическую последовательность, включая хуки, которые срабатывают еще до загрузки must-use плагинов и после shutdown.

24 нояб. 2017 г. 10:48:48