WordPress как на ладони
Шаблоны, плагины и темы для настоящих поклонников Elementor. От TemplateMonster.com wordpress jino

Как загружается WordPress

При работе с темами, плагинами и вообще с любым кодом WordPress, включая хаки в популярном файле темы functions.php. Хорошо бы знать в какой последовательности подключаются php файлы движка, когда срабатывают важные хуки и какие важные константы определены. В этой статье поговорим о такой последовательности загрузки.

Примеры

Чтобы было понятнее, возьмем простую задачу: нам нужно подключить какой-то код в админ-панели WordPress и только там - код не должен срабатывать во фронте или при AJAX запросах. Кто-то скажет, что достаточно сделать проверку с помощью is_admin(), однако это не так, потому что is_admin() вернет true и при AJAX запросе в файл admin-ajax.php.

Или например, можно подключить какую-то логику на хук admin_init и потом долго недоумевать, а почему моя логика работает и при запросах AJAX. Или почему она мешает плагинам, которые работают с AJAX...

Или вот еще пример из комментария. Когда в файле темы functions.php выполняется какой-то код, который зависит от другого кода подключаемого через хук init. Например, вы создали тип записи во время хука init и в самом файле functions.php выполняете проверку, которая опирается на этот новый тип записи и ожидаете что код будет работать, но это не так, потому что прямой код в functions.php срабатывает раньше чем событие init...

Таких примеров можно привести много. Но чтобы так не ошибаться, нужно разобраться и понять последовательность загрузки ядра WordPress. Этим мы и займемся.

Порядок загрузки (теория)

Понять логику загрузки не так сложно, как может показаться на первый взгляд. Для этого давайте взглянем на эту, столь любимую мной, картинку:

Порядок загрузки ядра WordPress

Теперь немного пояснений, чтобы все визуальное стало реальным...

Существует три варианта загрузки, хотя на самом деле их чуть больше, но это три основных:

  • Загрузка фронтэнда (темы).
  • Загрузка админки.
  • Загрузка через AJAX запрос (admin-ajax.php).

Во всех трех случаях всегда загружается основная часть - файл wp-load.php - это ядро WordPress. Т.е. ядро загружается всегда и везде.

Прежде чем переходить к каждому типу загрузки, давайте разберем порядок загрузки самого ядра.

Загрузка ядра WordPress

Ядро WP загружается при любом запросе: фронт, аякс, админка, REST ...

wp-load.php
	wp-config.php
		wp-settings.php

			// Функции загрузки (load): wp_debug_mode(), timer_start(), require_wp_db() ...
			// Функции констант: wp_initial_constants(), wp_cookie_constants() ...
			// Функции плагинов (хуки, активация): do_action(), plugin_dir_url(), register_activation_hook().

			// Устанавливаются константы: WP_MEMORY_LIMIT, WP_MAX_MEMORY_LIMIT, WP_DEBUG, SCRIPT_DEBUG, WP_CONTENT_DIR, WP_CACHE.

			// Стандартизируются переменные сервера: wp_fix_server_vars().

			// Проверяется режим разработки: wp_maintenance().

			// Включается таймер (скорость загрузки): timer_start().

			// Включается дебаг режим: wp_debug_mode().

			// Загружается 'wp-content/advanced-cache.php' если он есть и включено WP_CACHE.

			// База данных. $wpdb. require_wp_db().
			// Загружается 'wp-content/db.php' если есть и создается 
			// соединение с БД и все связанные переменные (префикс БД...).

			// Объектный кэш: 'wp-content/object-cache.php' если есть, или 'wp-include/cache.php'.

			// Подключаются базовые хуки (фильтры): default-filters.php.

			// Включается Multisite (если нужно)
			// Грузится 'wp-content/sunrise.php' если есть (только для multisite).

			// register_shutdown_function( 'shutdown_action_hook' )

			// SHORTINIT: остановка загрузки, где есть только самое базовое.
			if( SHORTINIT ) return false;

			// Подключаются функции локализации.

			// Проверяется установлен ли WP: wp_not_installed().

			// Подключается куча файлов с остальными функциями WordPress.

			// Подключается Must-use плагины и срабатывает событие:
			do_action( 'muplugins_loaded' );

			// Константы cookie, ssl: COOKIEPATH, COOKIE_DOMAIN
			// Общие глобальные переменные: $pagenow, $is_apache, $is_nginx, $is_lynx
			// Глоб. переменные клиента: $is_opera, $is_NS4, $is_safari, $is_chrome, $is_iphone, $is_IE, $is_edge

			// Подключаются Активные плагины.
			// Подключаются pluggable функции: pluggable.php.
			// Срабатывает
			do_action( 'plugins_loaded' );

			// Принудительные волшебные кавычки для значений: $_POST, $_REQUEST ... см. wp_magic_quotes() .

			// Глобальные переменные: 
			// $wp_query ($wp_the_query): экземпляр класса WP_Query.
			// $wp_rewrite: экземпляр класса WP_Rewrite, константы, функции и правила перезаписи.
			// $wp: экземпляр основного класса запроса WP (запускается позже).
			// $wp_widget_factory, $wp_roles

			// Текущая тема
			do_action( 'setup_theme' );
			// functions.php (child) - сначала подключается functions.php дочерней темы 
			// functions.php (parent) - затем подключается functions.php основной темы
			// Файл перевода WordPress: load_default_textdomain() 
			do_action( 'after_setup_theme' ); // первый хук доступный в теме

			// Определяется текущий пользователь (создается объект). 
			// Хотя его можно определить уже после события 'plugins_loaded'

			// init событие. Когда среда WP, плагины и тема активированны,
			// но на экран еще ничего не выведено:
			do_action( 'init' );

			// Регистрация виджетов: событие 'widget_init'

			// wp() - запускается основной запрос WP - $wp->main()

			// проверка статуса сайта для мультисайтовой сборки

			// тоже самое что init только после проверки статуса.
			// до этой строки работа PHP может не дойти...
			do_action( 'wp_loaded' );

Обратите внимание, что при загрузки ядра всегда подключаются файл темы functions.php, даже в админке WordPress, т.е. не важно, нужна нам тема или нет, functions.php работает и поэтому его можно поставить в один ряд с плагинами... Сделано так для удобства, чтобы любой код можно было «сунуть» в наш, потому и любимый, файл functions.php. Такое поведение не логично с точки зрения коддинга, но зато очень удобно с точки зрения разработки.

Итак, само ядро как мы видим находится в файле wp-settings.php, но перед ним вызывается wp-load.php. Нужно это для того, чтобы найти файл wp-config.php. Дело в том что wp-config.php может находится в одной папке со всеми файлами wordPress, а может быть вынесен в родительскую папку. Задача wp-load.php отыскать файл конфигурации и подключить его . Если его нигде нет, то WP предложит его создать. Собственно, ровно это происходит при установке WordPress.

После того, как файл конфигурации найден, он подключается. В нем указываются все важные константы, параметры подключения к базе данных и т.д. И затем подключается ядро - файл wp-settings.php.

Загрузка фронтэнда (темы)

Любые фронтэнд запросы отправляются в файл index.php в корневой папке домена. И это значит, что WordPress загружается с темой. Для констатации этого факта определяется константа WP_USE_THEMES. Так например хук template_redirect будет работать только, если определена эта константа.

А дальше процесс загрузки фонтенда выглядит так:

index.php
	// определяется константа WP_USE_THEMES

	wp-blog-header.php
		// ЯДРО (описано выше)
		require_once( dirname(__FILE__) . '/wp-load.php' );

		// установка основного запроса WordPress (среды WordPress). 
		// Тут определяется какая страница загружается. См. //wp-kama.ru/function/wp
		wp();

		// подключение нужного файла шаблона темы 'template-loader.php'
		require_once( ABSPATH . WPINC . '/template-loader.php' );

Больше тут добавить в общем-то нечего...

Подробнее про установку основного запроса и среду WP, читайте в описании функции wp(). Также есть полезная картинка о том как работает запрос WordPress:

Как работают функции запросов в WordPress

Про подключение нужно файла темы читайте: Иерархия шаблона.

Загрузка админки

Админка WordPress никак не связана с «корневым» файлом index.php. Вся её загрузка начинается с файла wp-admin/admin.php.

Первое и главной что там происходит - это определяется константа WP_ADMIN, которая говорит всему коду который выполняется потом, что мы находится в админке.

wp-admin/admin.php
	// определяется константа WP_ADMIN
	define( 'WP_ADMIN', true );

	// ЯДРО (описано выше)
	require_once(dirname(dirname(__FILE__)) . '/wp-load.php');

	// проверяется необходимость Апгрейда WordPress

	// подключаются файлы (дополнительные функции) админки
	require_once(ABSPATH . 'wp-admin/includes/admin.php');

	// Проверяет авторизован ли пользователь, перед тем как допустить его на любую страницу
	// если прав недостаточно, то юзер «улетит» на страницу авторизации
	auth_redirect();

	// хук админки
	do_action( 'admin_init' );

	// устанавливается данные текущей страницы
	set_current_screen();

	// шапка 
	require_once(ABSPATH . 'wp-admin/admin-header.php');

	// контент - тут логика разветвляется и контент загружается
	// либо от плагина
	// либо никакой, потому что это импорт данных
	// либо родные файлы адмники, например, wp-admin/options-general.php

	// подвал
	include(ABSPATH . 'wp-admin/admin-footer.php');

Загрузка через AJAX запрос

Отправлять AJAX запросы принято в файл wp-admin/admin-ajax.php, с него и начинается загрузка WordPress при AJAX запросах.

Давайте и тут разберем порядок загрузки, а затем немного пояснений.

wp-admin/admin.php
	// определяется константа WP_ADMIN
	define( 'WP_ADMIN', true );

	// ЯДРО
	require_once(dirname(dirname(__FILE__)) . '/wp-load.php');

	// Проверяется наличие параметра запроса 'action' он должен быть определен для любого AJAX запроса.
	if( empty( $_REQUEST['action'] ) ) die( '0' );

	// подключаются файлы (дополнительные функции) админки
	require_once(ABSPATH . 'wp-admin/includes/admin.php');

	// подключаются обработчики Ajax запросов ядра WordPress
	require_once( ABSPATH . 'wp-admin/includes/ajax-actions.php' );

	// хук админки
	do_action( 'admin_init' );

	// проверка и исправление значений параметра action связанных с ядром WordPress и добавление нужного хука
	add_action( 'wp_ajax_' . $_GET['action'], 'wp_ajax_' . str_replace( '-', '_', $_GET['action'] ), 1 );

	// проверка прав пользователя и запуск нужного хука
	do_action( 'wp_ajax_' . $_REQUEST['action'] );
	// или 
	do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] );

	// Ответ AJAX по умолчанию
	die( '0' );

При AJAX запросе также устанавливается константа WP_ADMIN. Это значит, что любой AJAX запрос выглядит для ядра, как запрос в админ часть, даже если этот запрос делается с фронта... Это не всегда нужно, но так принято в WordPress по причинам стандартизации и удобства использования.

Далее загружается ядро, в котором срабатывают все хуки. Т.е. подключаются и запускаются все плагины, срабатывает код файла functions.php, срабатывает событие init. Т.е. полностью загружается и обрабатывается ядро WordPress.

Теперь, когда ядро обработано, дополнительно подключаются все PHP функции админ-панели (хотя часто они не нужны) и запускается один из AJAX хуков (зависит от авторизации): wp_ajax_(action) или wp_ajax_nopriv_(action).

Запуск AJAX хука это последний этап - AJAX операция выполнена и она должна прервать работу PHP и вывести на экран какие-либо данные - обычно это либо просто строка, либо строка в json формате.

Кстати, для удобного json ответа при AJAX запросах в WP есть специальная функция - wp_json_encode() и две функции производные от нее:

Занимательная картинка о том как загружается WordPress

12 комментов
Полезные 1 Все
  • Приветствую. Вопрос такого рода. При AJAX запросах подключаются только файлы WordPress или же файлы плагинов тоже?

  • uptimizt cайт: github.com/uptimizt

    Все круто, но статья не полная без озвучки про WP JSON/REST API.
    До сих пор многие для AJAX используют admin ajax. Что тащит за собой кучу нагрузки, проблем и тормозов.

    Потому надо как можно больше сложных вычислений выносить в AJAX, но только не через админку, а через нативный REST API/WP JSON. и так можно решить 99% проблем с тормозами с заделом на будущее.

    Ошибка в том что вы AJAX ассоциируете с admin ajax. А это не так. Это не просто не точность, а дикая ошибка. Которая влечет то что джуны и мидлы в РФ в корне не верно понимают AJAX. Особенно вордпрессеры. Потому надо четко донести в статье о том что AJAX через admin только в админке. А на сайте это следует делать только через WP JSON/REST API. Вы ж библиотека русского ВордПресс. От вас зависит адекватность мышления людей. Давайте исправляться )

    Ответитьмесяц назад #
    • Kama6810

      Аякс это аякс, рест это рест, не надо путать это не одно и тоже, хоть и похоже и не редко взаимозаменяемо. В ВП AJAX - это admin ajax, только он может правильно найти конфиг файл, и именно для аякс запросов он и был создан (вместо него, при желании можно создать свой аналогичный файл без админ части.)! И он не тащит кучу нагрузки, без реальных тестов не поверю в это, чуть больше да, но никак не кучу!

      Кое где добавлю в статью пояснения насчет аякса, спс за коммент.

      REST API/WP JSON - это фронт и грузятся они также как и фронт, с минимальной разницей, там и правила ЧПУ срабатывают и все прочее, но детальнее это расписать пожалуй все же нужно, спс.

      От вас зависит адекватность мышления людей. Давайте исправляться )

      Не надо на меня обязанности и ответственности вешать, на ровном месте, я и так расписал так как никто не расписал. Адекватность людей зависит от людей, я тут не при чем...

      1
      Ответитьмесяц назад #
      • uptimizt cайт: github.com/uptimizt

        Аякс это аякс, рест это рест, не надо путать это не одно и тоже, хоть и похоже и не редко взаимозаменяемо.

        я нигде не утверждал что AJAX это REST. AJAX - это асинхронные запросы. REST - это протокол исполнения запросов.

        речь лишь о том что на фронте в 99% случаев правильно AJAX делать через REST API. но никак не черед admin ajax.

        пример с WooCommerce тут https://wp-kama.ru/handbook/wordpress/loading/comment-page-1#comment-24441

        Ответитьмесяц назад #
      • uptimizt cайт: github.com/uptimizt

        Извини если оскорбил и нагрузил ответственностью )

        Я хотел добавить что очень важно отразить 4ю группу нагрузки. У тебя их 3 - есть фронт, админка и AJAX (подразумевается AdminAjax). Но на самом деле важна именно 4я группа нагрузки - REST API.

        Потому в ядре есть 4 основных пути запросов и структуры хуков:

        • WP Admin
        • Admin Ajax - AJAX для админки
        • базовый init
        • REST API - AJAX для фронта

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

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

        У него кстати и своя структура и последовательность хуков.

        Ответить29 дней назад #
    • @ mihdan100 cайт: www.kobzarev.com

      Анатолий, тут надо сразу давать ссылку на твой последний пост "Шизокод и шизокодеры". От Тимура не зависит адекватность людей, если они шизокодеры или говнокодеры, уж простите, но из статьи слов не выкинешь mosking

      Рест появился значительно недавно, есть куча учебником и мануалов, где про него ни слова.

      И некоторые задачи все же надо решать при помощи админ аякс, а не реста.

      Вещи похожие, но применение разное.

      1
      Ответитьмесяц назад #
  • uptimizt cайт: github.com/uptimizt

    И некоторые задачи все же надо решать при помощи админ аякс, а не реста.

    например? что за задачи на фронте надо решать через админ?

    admin ajax - был придуман для работы аякс в админке. там и должен использоваться.

    то что его по не знанию начали тащить на фронт - издержки шаблонного мышления.

    ajax на фронте грамотные разработчики всегда делали через свои эндпоинты. например см как работает с AJAX тот же WooCommerce. он никогда не лезет в админ аякс.
    https://github.com/woocommerce/woocommerce/blob/master/includes/class-wc-ajax.php

    просто с приходом REST API - оно стало более понятно для джунов.

    Ответитьмесяц назад #
  • @ mihdan100 cайт: www.kobzarev.com

    REST API появился прям совсем недавно, жили же мы без него, используя admin-ajax.php как написано в Кодексе, и горя не знали.

    Мы реализуем через сердцебиение WP получение в реальном времени уведомлений для юзера в одном крупном проекте, он на старой версии ядра и обновлять мы его не собираемся по ряду причин, так что REST API нам там и не светитmosking

    Ответитьмесяц назад #
    • uptimizt cайт: github.com/uptimizt

      Да, ты прав. Я не разбирался как работает Hearbeat API и не использовал его на фронте. Только в админке.

      В этой части интересно узнать как у BuddyPress реализован похожий механизм сообщений в чате и уведомлений в панели.

      Если там тоже Hearbeat API то тут 4 варианта:

      • либо там разработчики поленились все написать на свой REST API
      • либо ждали тот что выйдет в WP из коробки
      • либо не знали что есть альтернатива админскому аяксу
      • либо в BP считается нормально тащить AJAX из админки на фронт (альтернатива подхода команды WooCommerce)
      1
      Ответить29 дней назад #
      • @ mihdan100 cайт: www.kobzarev.com

        Раньше в бадипрессе так и было, сейчас не могу сказать - уже пару лет ничего не приходилось на нем делать

        Ответить29 дней назад #
Здравствуйте, !     Войти . Зарегистрироваться