Как создать собственный кustomный виджет в WordPress: пошаговое руководство

Виджеты — один из основных способов расширить функциональность сайта на 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 — полезный навык, который позволяет гибко расширять функциональность сайта. В статье мы рассмотрели базовый пример, усложненный вариант с настройками, а также советы по безопасности и оптимизации. Экспериментируйте с виджетами и делайте сайт удобнее для себя и пользователей.

WooCommerce: автоматическое изменение стоимости товаров по расписанию с поддержкой вариаций
07.06.2026
Оптимизация базы данных WordPress: ударное решение для ускорения сайта
04.01.2026
WooCommerce: автоматическое отключение товара после продажи
10.06.2026
Как удалить или изменить атрибуты srcset в WordPress
16.03.2026
WooCommerce: как автоматически удалять товар после успешной оплаты без плагинов
28.04.2026