Транзиенты в WordPress: как кэшировать данные и запросы с примерами кода

Транзиенты в WordPress: как кэшировать данные и запросы с примерами кода

Кратко: транзиенты в WordPress — это встроенный механизм временного кеша: вы кладёте данные под ключом и указываете срок жизни, а WordPress сам удаляет запись, когда срок истёк. Три функции — set_transient(), get_transient() и delete_transient() — закрывают 90 % задач: кеширование тяжёлых запросов, ответов внешних API, результатов расчётов. Главные правила: всегда проверять результат на false, задавать осмысленный TTL, сбрасывать кеш при изменении данных и не хранить в транзиентах большие массивы и персональные данные. Ниже — устройство, рабочие примеры кода, ловушки и чек-лист.

Что такое транзиенты и зачем они нужны

Транзиент — это временная запись в базе (или в object cache), которая живёт заданное время. Механика простая: вы вычисляете результат — например, список популярных товаров или ответ внешнего сервиса — и сохраняете его под ключом на час. Следующие запросы получают готовое значение, а не пересчитывают всё заново.

Зачем это нужно на практике: тяжёлые запросы к базе выполняются на каждой загрузке страницы, а внешние API отвечают по 300–800 мс. Кеш на 15–60 минут снимает нагрузку с базы и ускоряет сайт без изменения логики. Транзиенты — самый дешёвый способ это сделать: они уже есть в ядре, не требуют плагинов и работают с любым кешем объектов, если он подключён.

Важно понимать, что транзиенты — не «вечный кеш». Это именно временное хранилище с автоматическим истечением, и его поведение зависит от того, есть ли на сайте постоянный object cache (Redis, Memcached).

Как устроены транзиенты

У транзиента три параметра: ключ (уникальная строка), значение (любая сериализуемая структура — строка, число, массив, объект) и срок жизни в секундах. Без object cache транзиенты хранятся в таблице wp_options двумя записями: _transient_<ключ> со значением и _transient_timeout_<ключ> со временем истечения.

С включённым постоянным object cache (Redis) та же запись уходит в память, а в базе остаётся только fallback. Это меняет поведение: кеш переживает перезагрузку страниц, но не обязательно переживает перезапуск Redis. Поэтому логика не должна полагаться на то, что значение «точно есть» — только на проверку и повторный расчёт.

Способ кеширования Что кеширует Где живёт Когда подходит
Транзиенты Произвольные данные и результаты запросов wp_options или object cache Тяжёлые выборки, ответы API, расчёты с TTL
Постоянный object cache Объекты WP_Query, термины, опции Redis / Memcached Высокая нагрузка, много запросов на страницу
Файловый / страничный кеш Готовый HTML страницы Файлы или CDN Анонимные посетители, статичные страницы
Плагины кеша HTML, CSS/JS, минификация Файлы, диск Общее ускорение без правок кода

Базовый паттерн: set, get, delete

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

$key = 'mytheme_top_posts';
$cached = get_transient( $key );

if ( false === $cached ) {
    $query = new WP_Query( array(
        'posts_per_page' => 10,
        'meta_key'       => 'views',
        'orderby'        => 'meta_value_num',
    ) );
    $cached = $query->posts;

    set_transient( $key, $cached, HOUR_IN_SECONDS );
}

foreach ( $cached as $post ) {
    // вывод
}

Ключевые моменты: проверка именно на false (а не на пустоту), ключ с префиксом темы или плагина, TTL константой (HOUR_IN_SECONDS, DAY_IN_SECONDS), чтобы не плодить «магические» числа. И самое частое: после публикации или обновления записи кеш нужно сбросить, иначе посетители увидят старые данные.

Сброс вешают на хуки сохранения — в этом помогают стандартные события WordPress, о которых подробно написано в статье хуки WordPress: actions и filters для новичка. Ещё полезно держать код в дочерней теме, а не в родительской, чтобы обновления темы ничего не сломали: дочерняя тема WordPress: как создать и зачем нужна.

Что кешировать и на сколько

Срок жизни — компромисс между свежестью данных и нагрузкой. Слишком короткий TTL не даёт эффекта, слишком длинный — показывает устаревшее. Ориентиры ниже проверены на реальных проектах.

Данные Разумный TTL Когда сбрасывать
Список популярных записей 15–60 минут По расписанию или при публикации
Ответ внешнего API (курсы, погода) 1–6 часов Форс-обновление при ошибке
Тяжёлый отчёт, агрегаты статистики 12–24 часа После импорта или пересчёта
Каталог, фасеты фильтров 30–120 минут При изменении товаров
Меню, справочники, настройки до недели При сохранении настроек

Ориентируйтесь на скорость изменения данных, а не на «чем дольше, тем лучше». Если данные обновляются раз в сутки, часовой TTL ничего не даёт, а суточный — нормален. Если это биржевые курсы, разумны минуты.

Кеширование ответов внешних API

Внешние сервисы — главный источник медленных страниц: один запрос может занимать секунду и больше. Транзиент на час снимает эту задержку и защищает от лимитов. Обязательно обрабатывайте ошибку: если API вернул ошибку, не кешируйте пустоту на час — лучше короткий TTL и повтор.

$key = 'mytheme_currency_rates';
$rates = get_transient( $key );

if ( false === $rates ) {
    $response = wp_remote_get( 'https://api.example.com/rates', array(
        'timeout' => 5,
    ) );

    if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
        $rates = array();
        set_transient( $key, $rates, 5 * MINUTE_IN_SECONDS );
    } else {
        $rates = json_decode( wp_remote_retrieve_body( $response ), true );
        set_transient( $key, $rates, HOUR_IN_SECONDS );
    }
}

Такой паттерн защищает от «шторма» запросов при недоступном API: сайт показывает последние известные или пустые данные, а не зависает. Если данные критичны, добавьте отдельный флаг ошибки и уведомление администратору — но не блокируйте страницу ожиданием ответа.

Ловушки, о которых узнают на проде

Первая и самая частая: проверка на пустоту вместо false. Функция возвращает false при промахе, но ваши данные тоже могут быть пустым массивом — и тогда кеш будет пересчитываться каждый раз. Проверяйте строго: if ( false === $cached ).

Вторая: хранение больших массивов. Транзиент с тысячей объектов раздувает wp_options и замедляет автозагрузку, если запись попала в autoload. Для больших объёмов лучше объектный кеш или отдельная таблица.

Третья: TTL без инвалидации. Кеш «на час» нормален, но если админ изменил товар, а кеш живёт ещё 40 минут, вы получите баг-репорт. Сбрасывайте кеш на событиях сохранения и публикации. Четвёртая: транзиенты в мультисайте и в CLI-контексте ведут себя по-разному — проверяйте на реальном окружении.

Пятая: забытый префикс в ключе. Два плагина с ключом top_posts затирают друг друга. И шестая: кеширование персональных данных — get_transient() общий для всех, поэтому корзина или данные пользователя в транзиенте утекут другому посетителю. Персональные данные в транзиентах не хранят.

Когда транзиенты — плохой выбор

Есть задачи, где транзиенты вредны. Например, хранение денежных остатков, которые должны быть точными в момент продажи: кеш на час приведёт к продаже отсутствующего товара. Не подходят они и для данных, которые обязаны быть консистентными между запросами (счётчики, блокировки, очереди) — для этого нужны транзакции и отдельные таблицы.

Плохой выбор — и кеширование того, что уже кешируется ядром: WP_Query с постоянным object cache, термины, опции. Двойной кеш только усложняет инвалидацию. И совсем не стоит класть в транзиенты большие бинарные данные и HTML целых страниц: для этого есть страничный кеш и CDN.

Отдельно про тяжёлые SQL-запросы: если выборка медленная, сначала проверьте индексы и сам запрос — примеры безопасной работы с базой есть в статье $wpdb в WordPress: безопасные запросы. Транзиент ускоряет повторные вызовы, но не лечит плохой запрос.

Типичные ошибки

Ошибки почти всегда одни и те же, и все они дешёво ловятся на ревью. Ниже — короткий список для самопроверки.

Ошибка Последствие Как правильно
Проверка на пустоту вместо false Кеш не работает, нагрузка как без него Строгое сравнение с false
Большой массив в транзиенте Раздувание wp_options, медленная автозагрузка Object cache или своя таблица
Нет инвалидации Устаревшие данные после правок delete_transient на save_post
Кеш ошибок API надолго Сайт часами показывает пустоту Короткий TTL при ошибке, повтор
Ключ без префикса Конфликт с другими плагинами Префикс темы или плагина
Персональные данные в кеше Утечка между посетителями Кешировать только общие данные

Отладка простая: включите WP_DEBUG, посмотрите, какие ключи создаются, и проверьте, не растёт ли таблица опций. Если транзиентов стало слишком много, поможет очистка по расписанию — как устроен планировщик, разобрано в статье WP-Cron: планировщик задач WordPress.

Чек-лист внедрения

1. Определите, что именно тормозит: запрос, API или расчёт. 2. Выберите TTL по скорости изменения данных. 3. Оберните вычисление в get/set с проверкой на false. 4. Добавьте префикс в ключ. 5. Повесьте сброс кеша на события сохранения и публикации. 6. Обработайте ошибки внешнего API коротким TTL. 7. Не храните персональные данные и большие массивы. 8. Проверьте поведение с включённым и выключенным object cache. 9. Убедитесь, что кеш не мешает админке и редактору. 10. Замерьте время ответа до и после — эффект должен быть виден в цифрах.

Для замеров достаточно записать время генерации страницы в лог и сравнить до и после. Если выигрыша нет, значит кеш стоит не там, где надо, или TTL слишком короткий.

TimeWeb

Частые вопросы про транзиенты WordPress

Чем транзиенты отличаются от object cache?

Транзиенты — это API для временного хранения произвольных данных с TTL. Object cache — слой кеширования объектов WordPress (запросов, терминов, опций). Если постоянный object cache включён, транзиенты автоматически хранятся в нём, а не в базе. То есть транзиенты — ваш инструмент, object cache — инфраструктура под ними.

Что вернёт get_transient, если записи нет или срок истёк?

Функция вернёт false. Поэтому проверять результат нужно строго через if ( false === $cached ), а не через пустоту: пустой массив — это тоже валидные данные, и при нестрогой проверке кеш будет пересчитываться на каждом запросе.

Какой TTL выбрать для кеша запросов?

Зависит от скорости изменения данных: популярные записи — 15–60 минут, ответы внешних API — 1–6 часов, агрегаты и отчёты — 12–24 часа. Общее правило: TTL не длиннее, чем допустимая для вас задержка обновления. Если данные меняются сразу и кеш недопустим — кешировать не нужно.

Как сбросить транзиент при публикации записи?

Повесить удаление на хуки save_post и deleted_post: внутри хука вызывать delete_transient с теми же ключами, что использует вывод. Если ключей много, используйте общий префикс и удаляйте группу по списку. Это дешевле, чем ждать истечения TTL, и снимает жалобы «на сайте старые данные».

Можно ли хранить в транзиентах большие массивы?

Нежелательно. Крупные записи раздувают wp_options и замедляют автозагрузку, а с object cache занимают память Redis. Для больших объёмов лучше отдельная таблица или кеширование частями. Ориентир: если данные больше десятков килобайт, транзиент — не лучшее место.

Видны ли транзиенты посетителям сайта и безопасны ли они?

Сама запись не видна в браузере, но get_transient общий для всех посетителей: что положили — то получат все. Поэтому в транзиентах нельзя хранить персональные данные, корзины и токены. Кешируйте только общие данные: списки записей, справочники, ответы API.

Вывод

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

Главное — не превращать кеш в свалку: не хранить большие массивы и персональные данные, не кешировать ошибки надолго и всегда иметь план инвалидации. Тогда сайт будет быстрее, а данные — актуальными.

Если нужна доработка кеширования, оптимизация запросов или ускорение сайта — эту задачу можно передать одной команде. Мы находим узкие места, настраиваем object cache и транзиенты, чистим раздутые опции и проверяем результат замерами. Посмотрите услуги разработки и поддержки сайтов, изучите портфолио проектов и почитайте блог о WordPress. Опишите задачу через форму контактов — предложим решение и рассчитаем стоимость.

Clearfy

Поделиться:
Telegram ВКонтакте