Виджет WordPress: случайная запись с миниатюрой

Многие ищут готовый плагин, который делает ровно то, что нужно. Но если у вас есть базовые навыки PHP и понимание структуры WordPress, часто проще написать собственный виджет. В этой статье шаг за шагом создадим виджет, который выбирает одну случайную запись, берёт её featured image (миниатюру) и выводит в сайдбар как визуальную рекомендацию для посетителей.
Это продолжение серии по кастомизации тем WordPress. Если вы только начинаете — коротко: виджет — это PHP‑класс, который регистрируется через API виджетов WordPress. Внутри класса вы создаёте форму настроек, обработчик обновления и функцию вывода (widget), где и размещается ваш запрос к базе и цикл (The Loop).
Что мы делаем и зачем
Задача: показывать одну случайную публикацию со связанным изображением в сайдбаре. Это помогает повысить вовлечённость и даёт посетителю повод перейти в другие части сайта.
Кому пригодится: блогерам, владельцам медиа и всем, кто хочет увеличить внутреннюю навигацию на сайте.
Ключевые концепции: запросы WordPress и цикл
Определения в одну строку:
- Запрос (query): параметры, которыми WordPress выбирает набор записей из базы. Пример: «последние 10 записей».
- Цикл (The Loop): стандартный способ пройти по результатам запроса и вывести содержимое каждой записи.
Каждая страница в WordPress выполняет один или несколько запросов. Вы можете добавить дополнительные запросы в шаблоне или внутри виджета. Для виджета мы сделаем отдельный запрос, который вернёт одну случайную запись вместе с миниатюрой.
Важно: есть несколько способов сделать запрос. query_posts() изменяет глобальный главный запрос и обычно не рекомендуется. Гораздо безопаснее использовать WP_Query или get_posts(), чтобы не ломать основной вывод страницы.
Базовый код виджета
Создайте файл в каталоге вашего сайта wp-content/plugins, например random-post-widget.php. Писать можно прямо на сервере или локально, а затем загрузить файл.
Ниже — минимальный рабочий шаблон плагина и класса виджета. Это «скелет», в который мы добавим функциональность.
'RandomPostWidget', 'description' => 'Displays a random post with thumbnail');
parent::__construct('random_post_widget', 'Random Post and Thumbnail', $widget_ops);
}
public function form($instance)
{
$instance = wp_parse_args((array) $instance, array('title' => ''));
$title = $instance['title'];
?>
Это мой новый виджет!";
echo $args['after_widget'];
}
}
add_action('widgets_init', function(){ register_widget('RandomPostWidget'); });Этот код создаёт виджет с настройкой для названия. На данный момент функция widget() просто выводит статическое сообщение — дальше мы заменим это на запрос и вывод миниатюры.
Простейший запрос и цикл
Чтобы получить список записей, можно использовать query_posts(), но лучше использовать WP_Query. Сначала покажу самый простой пример с query_posts() для понимания, затем — рекомендуемый вариант.
Замените место “// WIDGET CODE GOES HERE” на этот минимальный код (пример для понимания):
// НЕ рекомендуется в продакшене: изменяет глобальный цикл
query_posts('');
if (have_posts()) :
while (have_posts()) : the_post();
the_title();
endwhile;
endif;
wp_reset_query();Этот пример просто выводит заголовки по умолчанию (обычно 10 последних записей). Лучше оформить вывод HTML и ссылки:
query_posts('');
if (have_posts()) :
echo '';
while (have_posts()) : the_post();
echo '- ' . get_the_title() . '
';
endwhile;
echo '
';
endif;
wp_reset_query();Но мы хотим одну запись и случайную сортировку. Параметры можно задать прямо в строке запроса:
query_posts('posts_per_page=1&orderby=rand');Обновите вывод, чтобы показать миниатюру. Пример с query_posts():
query_posts('posts_per_page=1&orderby=rand');
if (have_posts()) :
echo '';
endif;
wp_reset_query();Этот код работает, но есть важные замечания по производительности и безопасности ниже.
Рекомендуемый вариант: WP_Query и безопасный вывод
Используйте WP_Query, чтобы не изменять глобальный запрос. Также экранируйте вывод и используйте кеширование, чтобы снизить нагрузку.
Пример кода внутри метода widget():
// Рекомендуемый вариант с WP_Query
$cache_key = 'rpw_random_post_' . get_current_blog_id();
$cached = get_transient($cache_key);
if ($cached !== false) {
echo $cached;
} else {
$args = array(
'posts_per_page' => 1,
'orderby' => 'rand',
'post_status' => 'publish',
);
$q = new WP_Query($args);
ob_start();
if ($q->have_posts()) {
echo '';
}
wp_reset_postdata();
$output = ob_get_clean();
// Кешируем результат на короткий срок, например 10 минут
set_transient($cache_key, $output, 10 * MINUTE_IN_SECONDS);
echo $output;
}Пояснения:
- WP_Query безопасно изолирует запрос от основного цикла.
- esc_url() и esc_html() защищают вывод от XSS.
- get_the_post_thumbnail() возвращает корректный HTML для изображения.
- transient API используется для кеширования, чтобы не запускать случайный запрос на каждой загрузке страницы.
Варианты и улучшения
- Альтернатива: get_posts()
- Если вам нужен простой массив записей без сложных настроек, используйте get_posts($args). Он удобен для одноразовых выборок.
- Ограничение по рубрике или метке
- Добавьте параметры ‘cat’ или ‘tax_query’ в $args, чтобы показывать записи только из нужной категории.
- Несколько записей
- Установите posts_per_page > 1 и адаптируйте HTML в виджете для списка миниатюр.
- Замена порядка сортировки
- Вместо rand можно выбрать orderby => ‘date’ или мощные соритровки по метаданным.
- Ленивая загрузка изображений
- Для производительности добавьте loading=”lazy” к тэгу img (можно фильтровать через post_thumbnail_html).
Безопасность и производительность
Важно:
Никогда не выводите данные без экранирования. Для URL — esc_url(), для текста — esc_html(), для атрибутов — esc_attr().
Рекомендации:
- Используйте WP_Query или get_posts() вместо query_posts().
- Кешируйте результат с помощью transients или внешнего кеша (Redis, Memcached).
- Ограничьте частоту обновления кеша — например, 5–30 минут в зависимости от частоты обновления контента.
- Если на сайте много трафика, разгрузите виджет через fragment caching или статический HTML.
Совместимость и версии WordPress
Работает с большинством версий WordPress текущих лет. Если у вас очень старая тема, убедитесь, что:
- Функция get_the_post_thumbnail поддерживается (включена с WP 3.0+).
- Ваша тема использует поддержку миниатюр (add_theme_support(‘post-thumbnails’)).
Если виджет не отображается, проверьте логи PHP и активность плагина.
Отладка и распространённые проблемы
Проверьте по шагам:
- Плагин активирован в админке «Плагины».
- Виджет добавлен в сайдбар через Внешний вид → Виджеты.
- У записей есть миниатюры и статус publish.
- Нет фатальных ошибок PHP — включите WP_DEBUG в локальной среде.
- Кеш не содержит устаревший HTML — попробуйте удалить transient с помощью delete_transient().
Типичные симптомы и решения:
- Пустой вывод: убедитесь, что в базе есть опубликованные записи с миниатюрами.
- Неправильное изображение: проверьте размеры и наличие image sizes в теме.
- Повторяющаяся одна и та же запись часто: уменьшите время кеша или отключите кеширование при тестировании.
Критерии приёмки
- Виджет успешно регистрируется и доступен в панели Виджеты.
- При добавлении в сайдбар выводится одна случайная опубликованная запись.
- Изображение и заголовок кликабельны и ведут на страницу записи.
- Все внешние данные экранированы (esc_url, esc_html).
- Кеширование работает и снижает количество запросов к БД.
Контрольный список по ролям
Для разработчика:
- Написать и зарегистрировать класс виджета.
- Реализовать безопасный WP_Query и вывод.
- Добавить кеширование и сброс транзиентов.
Для контент‑менеджера:
- Убедиться, что у записей есть миниатюры.
- Добавить подходящую категорию/теги при необходимости.
Для администратора сайта:
- Активировать плагин и добавить виджет в сайдбар.
- Проверить нагрузку на БД после активации.
Короткое руководство по развертыванию
- Создайте файл random-post-widget.php в wp-content/plugins.
- Вставьте код плагина (см. раздел выше).
- Активируйте плагин в админ‑панели WordPress → Плагины.
- Перейдите в Внешний вид → Виджеты и перетащите Random Post and Thumbnail в сайдбар.
- При необходимости настройте заголовок виджета и время кеша.
Критические примеры, когда подход не подходит
- Сайт с тысячами записей и частыми обновлениями: частые рандомные запросы без кеша создадут нагрузку на БД.
- Сайты с высокими требованиями к SEO: случайный показ популярных материалов может мешать контролю над внутренней перелинковкой.
- Если темы или плагины вмешиваются в глобальный цикл через query_posts(), используйте изолированный WP_Query.
Короткий глоссарий
- WP_Query — класс для выполнения запросов к записям WordPress.
- The Loop — стандартный цикл для вывода найденных записей.
- transient — временный кеш в базе данных WordPress.
Вывод
Создать собственный виджет для WordPress просто. Начните с простого кода, затем улучшайте: замените query_posts() на WP_Query, экранируйте вывод, добавьте кеширование и опции для администратора. Такой подход даёт гибкость и контроль над тем, как пользователи видят дополнительные материалы на вашем сайте.
Кратко:
- Используйте WP_Query для безопасных выборок.
- Экранируйте все внешние данные.
- Кешируйте вывод, если сайт получает значительный трафик.
Заметки:
- Если вы хотите расширить функциональность (несколько миниатюр, фильтрация по категории, опции в админке), добавьте поля в метод form() и сохраняйте их в update().
Похожие материалы
Не видно файлов в WSL — быстрое решение
Ошибка RdrCEF.exe в Adobe Reader — как исправить
Дополнения Firefox для GIF: задержка, пауза, создание
Автономные файлы в Windows 11: включение и отключение
Ошибка Hulu P-DEV323 — как исправить