Обработка запроса в WordPress: как устроено внутри
Почему сайт на WordPress начинает тормозить на сотне одновременных посетителей, а плагин вызывает конфликт только на определённых страницах — разбираем жизненный цикл запроса от HTTP до HTML.

На сотне одновременных запросов типичный WordPress-сайт начинает отдавать страницы по три-четыре секунды вместо обычных 300 миллисекунд, а на ста пятидесяти может вообще перестать отвечать. Не потому, что код плох — просто каждый запрос проходит через десятки этапов инициализации, сотни хуков и несколько обращений к базе данных, даже если в итоге отдаёт одну и ту же страницу «О компании». Понимание того, как WordPress обрабатывает запрос от момента, когда веб-сервер передал управление PHP, до момента, когда HTML улетел в браузер, показывает, где искать узкие места и почему плагины конфликтуют друг с другом.
От HTTP до загрузки ядра
Веб-сервер получает запрос, смотрит в правила и передаёт всё, что не является файлом, на index.php в корне установки WordPress. Этот файл делает ровно одно: подключает wp-blog-header.php, который запускает цепочку загрузки ядра через wp-load.php. На этом этапе WordPress ещё ничего не знает о запрошенном URL — он просто готовит окружение.
Файл wp-load.php ищет wp-config.php, который содержит параметры подключения к базе данных и ключи безопасности, затем подключает wp-settings.php. Именно wp-settings.php делает основную работу: регистрирует автозагрузку классов, определяет константы, подключает функции ядра, инициализирует мультисайт, если он включён, и загружает активные плагины из базы данных — каждый указанный файл подключается через require в порядке активации.
Цена загрузки плагинов
На этапе загрузки активных плагинов WordPress просто подключает их главные PHP-файлы по очереди. Плагин может выполнить любой код на верхнем уровне: обратиться к базе, создать глобальные объекты, зарегистрировать хуки. Двадцать активных плагинов — это двадцать отдельных require и потенциально двадцать обращений к базе при инициализации каждого. Порядок подключения зависит только от порядка активации, а не от зависимостей, поэтому конфликты «плагин А не видит функций плагина Б» решаются только изменением порядка активации или использованием хуков.
Разбор запроса и формирование главного запроса
После загрузки плагинов WordPress создаёт глобальный объект $wp — экземпляр класса WP, который отвечает за разбор URL и маршрутизацию. Метод parse_request этого объекта берёт REQUEST_URI из суперглобального массива $_SERVER, удаляет базовый путь установки, если WordPress стоит в подкаталоге, и сопоставляет оставшийся путь с набором правил перезаписи — rewrite rules.
Правила перезаписи хранятся в опции rewrite_rules в базе данных. Это ассоциативный массив регулярных выражений: каждое правило сопоставляет шаблон URL с набором переменных запроса. Например, шаблон category/(.+?) превращается в category_name=$matches[1]. WordPress перебирает правила по очереди — первое совпадение выигрывает. Если ни одно правило не подошло, WordPress считает, что запрашивается главная страница.
| Этап | Что происходит | Типичное узкое место |
|---|---|---|
| Загрузка ядра | Подключение wp-config, wp-settings, автозагрузка классов | Опции с autoload в базе |
| Загрузка плагинов | Последовательный require файлов плагинов | Инициализация каждого плагина |
| Разбор URL | Сопоставление с rewrite rules | Перебор всех правил до первого совпадения |
| Главный запрос | Формирование SQL через WP_Query | Сложные запросы с JOIN и метаполями |
| Загрузка шаблона | Поиск файла шаблона в теме и родительской теме | Обычно быстро |
| Рендеринг | Выполнение PHP-кода шаблона, хуки в теле страницы | Виджеты и шорткоды |
Извлечённые переменные запроса передаются в объект WP_Query — это главный запрос страницы. WP_Query принимает массив параметров и формирует SQL-запрос к таблицам постов и метаданных. На этом этапе срабатывают хуки, которые позволяют плагинам изменить запрос: например, добавить фильтр по метаполю или исключить посты определённой категории.
Выбор шаблона и рендеринг
После выполнения главного запроса WordPress знает, какой тип контента нужно отобразить: одиночный пост, архив категории, страницу 404. Класс WP отправляет заголовки HTTP и вызывает функцию, которая определяет, какой файл шаблона использовать. Для каждого типа контента существует иерархия файлов: например, для одиночного поста WordPress ищет сначала single-{post-type}-{slug}.php, потом single-{post-type}.php, потом single.php, и в конце index.php. Первый найденный файл подключается через require.
Каждый запрос проходит через одинаковую цепочку загрузки, даже если страница закеширована на уровне плагина — плагин кеширования обычно подключается на раннем хуке и прерывает выполнение до этапа формирования запроса, но ядро и все плагины уже загружены.
Внутри шаблона выполняется обычный PHP-код: функции типа the_title(), the_content() извлекают данные из глобального объекта $post, который был заполнен результатами главного запроса. Каждая из этих функций запускает собственные хуки1: например, the_content() применяет фильтр the_content к тексту поста, и любой плагин может зарегистрировать callback, который изменит или дополнит содержимое.
Хуки и порядок выполнения
Система хуков — это единственный официальный способ расширять WordPress без правки файлов ядра. Существуют два типа хуков: actions и filters. Actions позволяют выполнить произвольный код в определённой точке, filters — изменить передаваемое значение. За время обработки одного запроса срабатывают сотни хуков: от ранних init и wp_loaded до поздних wp_head и wp_footer внутри HTML.
Проблемы возникают, когда два плагина регистрируют callback на один и тот же хук с одинаковым приоритетом, но зависят от порядка выполнения друг друга. Или когда плагин на хуке parse_request делает медленный внешний HTTP-запрос — это блокирует обработку каждого входящего посетителя.
Где это ломается и как измерить
Типичные точки замедления:
- Автозагружаемые опции. WordPress загружает все опции с флагом autoload='yes' одним запросом при инициализации и держит в памяти. Если плагины записали туда несколько мегабайт данных, каждый запрос начинается с вытягивания этого объёма из базы. Проверяется запросом
SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'и измерением размера результата. - Rewrite rules. Тысяча правил перезаписи — это тысяча регулярных выражений, которые WordPress перебирает для каждого URL. Возникает, когда плагин или тема регистрируют правила для каждого поста отдельно. Правила хранятся в опции rewrite_rules — посмотрите её размер через wp_options.
- Запросы с метаполями. WP_Query с фильтром по meta_key формирует JOIN к таблице postmeta, которая обычно не проиндексирована под конкретные ключи. Запрос вида «посты, у которых meta_key='price' и meta_value > 1000» сканирует всю таблицу.
- Хуки с внешними вызовами. Если плагин на раннем хуке обращается к внешнему API без таймаута или кеша, каждый запрос к сайту ждёт ответа от третьей стороны.
Для измерения используйте плагины профилирования типа Query Monitor или включайте логирование медленных запросов на уровне MySQL. Query Monitor показывает время каждого SQL-запроса, сработавшие хуки и их длительность, использование памяти по этапам.
Версии и точки выхода
Описанный порядок актуален для WordPress 6.x. В более ранних версиях 5.x механизм идентичен, изменения касались только внутренней реализации REST API и блочного редактора, которые добавили собственные наборы хуков, но не изменили базовый жизненный цикл запроса.
Плагины кеширования перехватывают выполнение на стадии до загрузки шаблона: они встраивают код в начало wp-config.php или используют advanced-cache.php, который подключается до загрузки плагинов. Если закешированная версия найдена, выполнение прерывается, и HTML отдаётся напрямую — это позволяет избежать разбора запроса и работы с базой, но ядро и константы уже загружены.
Что делать дальше
Установите Query Monitor и откройте несколько типов страниц: главную, одиночный пост, архив категории, страницу поиска. Посмотрите на количество SQL-запросов и список сработавших хуков. Если запросов больше пятидесяти на простой странице без комментариев — ищите плагин, который делает запросы в цикле. Если время отклика больше секунды при пустом кеше — смотрите на автозагружаемые опции и размер rewrite rules. На продакшене настройте объектное кеширование через Redis или Memcached — это снимает нагрузку с базы, но не отменяет загрузку плагинов на каждом запросе.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: WordPress Developer Resources — Plugin API, Query Monitor — отладка и профилирование WordPress
Частые вопросы
Почему WordPress загружает все плагины на каждом запросе, даже если они не нужны на конкретной странице?
Можно ли ускорить обработку запроса, если кешировать результат разбора rewrite rules?
Если у меня стоит плагин кеширования, зачем понимать жизненный цикл запроса?
Как узнать, какой плагин вызывает медленный запрос к базе?
А если обновиться до новой мажорной версии WordPress — изменится ли порядок загрузки и разбора запроса?
Что делать, если два плагина конфликтуют и сайт выдаёт белый экран только на определённых страницах?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.