Виджеты — один из основных способов расширить функциональность сайта на WordPress, добавляя в сайдбар, футер или другие области кастомные блоки. В этой статье мы подробно рассмотрим, как создать собственный кustomный виджет, который легко интегрируется в любую тему WordPress и управляется из админки.
Что такое виджеты и зачем создавать собственные
Виджеты — это небольшие блоки контента, которые можно размещать в специально отведенных областях темы, называемых сайдбарами или widget areas. По умолчанию WordPress предоставляет базовый набор виджетов: текст, последние записи, категории и другие. Однако часто возникает необходимость сделать уникальный виджет, который будет выполнять специфическую задачу — отображать данные из API, показывать кастомные посты, выводить форму обратной связи и многое другое.
Создание собственного виджета позволяет:
- Полностью контролировать внешний вид и функциональность блока.
- Добавлять уникальный функционал без установки сторонних плагинов.
- Обеспечить удобство управления контентом через встроенный интерфейс WordPress.
Далее рассмотрим, как это реализовать на практике.
Основные шаги создания кustomного виджета в WordPress
Чтобы создать виджет, нужно создать класс, который наследуется от WP_Widget, и зарегистрировать его через хук widgets_init. Давайте разберем каждый шаг подробно.
1. Создаем класс виджета
Вот базовый каркас класса виджета для сайта wpmart.ru:
class WPMart_Custom_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'wpmart_custom_widget',
__('WPMart Custom Widget', 'wpmart'),
['description' => __('Пример собственного виджета для WPMart', 'wpmart')]
);
}
public function widget($args, $instance) {
echo $args['before_widget'];
if (!empty($instance['title'])) {
echo $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title'];
}
echo '<p>Это пример содержимого собственного виджета WPMart.</p>';
echo $args['after_widget'];
}
public function form($instance) {
$title = !empty($instance['title']) ? $instance['title'] : __('Новый заголовок', 'wpmart');
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php _e('Заголовок:'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text" value="<?php echo esc_attr($title); ?>">
</p>
<?php
}
public function update($new_instance, $old_instance) {
$instance = [];
$instance['title'] = (!empty($new_instance['title'])) ? sanitize_text_field($new_instance['title']) : '';
return $instance;
}
}В этом коде мы определили конструктор, метод widget для вывода содержимого, form — для создания формы настроек в админке и update для сохранения настроек.
2. Регистрируем виджет
Теперь необходимо зарегистрировать виджет, чтобы WordPress его увидел. Добавьте следующий код в файл functions.php вашей темы или в плагин:
function wpmart_register_custom_widget() {
register_widget('WPMart_Custom_Widget');
}
add_action('widgets_init', 'wpmart_register_custom_widget');После этого в разделе Внешний вид → Виджеты в админке появится наш виджет «WPMart Custom Widget».
Расширение виджета: добавление настроек и динамического контента
Чтобы сделать виджет полезнее, можно добавить дополнительные поля в форму настроек и вывести динамический контент. Например, создадим виджет, который выводит список последних записей определенной категории.
Пример: виджет последних записей из заданной категории
Расширим наш класс:
class WPMart_Recent_Posts_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'wpmart_recent_posts',
__('WPMart Последние записи по категории', 'wpmart'),
['description' => __('Выводит последние записи из выбранной категории', 'wpmart')]
);
}
public function widget($args, $instance) {
echo $args['before_widget'];
if (!empty($instance['title'])) {
echo $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title'];
}
$category_id = !empty($instance['category']) ? intval($instance['category']) : 0;
$posts_count = !empty($instance['count']) ? intval($instance['count']) : 5;
$query_args = [
'cat' => $category_id,
'posts_per_page' => $posts_count,
'post_status' => 'publish'
];
$recent_posts = new WP_Query($query_args);
if ($recent_posts->have_posts()) {
echo '<ul>';
while ($recent_posts->have_posts()) {
$recent_posts->the_post();
echo '<li><a href="' . esc_url(get_permalink()) . '">' . esc_html(get_the_title()) . '</a></li>';
}
echo '</ul>';
} else {
echo '<p>' . __('Записей не найдено', 'wpmart') . '</p>';
}
wp_reset_postdata();
echo $args['after_widget'];
}
public function form($instance) {
$title = !empty($instance['title']) ? $instance['title'] : __('Последние записи', 'wpmart');
$category = !empty($instance['category']) ? $instance['category'] : '';
$count = !empty($instance['count']) ? $instance['count'] : 5;
$categories = get_categories(['hide_empty' => false]);
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php _e('Заголовок:'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text" value="<?php echo esc_attr($title); ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('category')); ?>"><?php _e('Категория:'); ?></label>
<select id="<?php echo esc_attr($this->get_field_id('category')); ?>" name="<?php echo esc_attr($this->get_field_name('category')); ?>" class="widefat">
<option value="">-- <?php _e('Выберите категорию', 'wpmart'); ?> --</option>
<?php foreach ($categories as $cat): ?>
<option value="<?php echo esc_attr($cat->term_id); ?>" <?php selected($category, $cat->term_id); ?>><?php echo esc_html($cat->name); ?></option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('count')); ?>"><?php _e('Количество записей:'); ?></label>
<input id="<?php echo esc_attr($this->get_field_id('count')); ?>" name="<?php echo esc_attr($this->get_field_name('count')); ?>" type="number" value="<?php echo esc_attr($count); ?>" min="1" max="20" class="tiny-text">
</p>
<?php
}
public function update($new_instance, $old_instance) {
$instance = [];
$instance['title'] = (!empty($new_instance['title'])) ? sanitize_text_field($new_instance['title']) : '';
$instance['category'] = (!empty($new_instance['category'])) ? intval($new_instance['category']) : 0;
$instance['count'] = (!empty($new_instance['count'])) ? intval($new_instance['count']) : 5;
return $instance;
}
}В этом примере виджет позволяет администратору выбрать категорию и количество выводимых записей. В методе widget мы делаем запрос с помощью WP_Query и выводим список.
Использование плагинов для расширения функционала виджетов
Помимо написания собственного кода, для создания виджетов можно использовать плагины, которые упрощают задачу и предоставляют готовые решения.
Популярные плагины для виджетов
- Widget Options — расширенный контроль видимости и настроек виджетов.
- Custom Sidebars — позволяет создавать новые области виджетов и назначать их на страницы.
- SiteOrigin Widgets Bundle — набор готовых виджетов с визуальным редактором.
Использование таких плагинов удобно, если вы не хотите писать код или нуждаетесь в быстром решении.
Советы по оптимизации и безопасности виджетов
Правильная очистка данных
Обязательно используйте функции очистки данных при сохранении настроек виджета, такие как sanitize_text_field, intval и другие. Это защитит сайт от XSS и других уязвимостей.
Кэширование вывода
Если виджет делает тяжелые запросы (например, к API или базе), стоит реализовать кэширование, чтобы снизить нагрузку на сервер. Можно использовать Transients API:
function wpmart_get_cached_widget_data($key, $callback, $expiration = 3600) {
$data = get_transient($key);
if ($data === false) {
$data = call_user_func($callback);
set_transient($key, $data, $expiration);
}
return $data;
}Так вы можете обернуть тяжелые запросы и экономить ресурсы.
Поддержка перевода
Используйте функции локализации, такие как __() и _e(), чтобы обеспечить поддержку нескольких языков.
Итог
Создание собственного виджета в WordPress — полезный навык, который позволяет гибко расширять функциональность сайта. В статье мы рассмотрели базовый пример, усложненный вариант с настройками, а также советы по безопасности и оптимизации. Экспериментируйте с виджетами и делайте сайт удобнее для себя и пользователей.