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

В этой статье мы подробно разберём, как создать собственный виджет для WordPress с нуля. Виджеты — это удобный инструмент для добавления функционала в боковые панели и другие области темы без необходимости править исходный код шаблона. Создание собственного виджета расширит возможности вашего сайта и позволит добавить именно тот функционал, который вам нужен.

Что такое виджеты в WordPress и зачем создавать свои

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

Однако часто стандартных виджетов недостаточно, и приходится искать плагины. Но если ни один из существующих плагинов не подходит, или хочется реализовать уникальный функционал, то логично создать свой собственный виджет. Это даст полный контроль над выводом и поведением блока.

Например, можно создать виджет для вывода произвольного текста с настройками, список избранных записей, форму подписки, персонализированное приветствие и многое другое.

Основы создания виджета WordPress: класс WP_Widget и его методы

Для создания виджета нужно создать класс, который наследуется от встроенного класса WP_Widget. В этом классе необходимо реализовать как минимум три метода:

  • __construct() — конструктор, где задаются название виджета и описание;
  • widget($args, $instance) — метод, который выводит содержимое виджета на сайте;
  • form($instance) — метод, который выводит форму настроек виджета в админке;
  • update($new_instance, $old_instance) — метод для обработки и сохранения настроек виджета.

Также нужно зарегистрировать виджет, используя хук widgets_init.

Пример простого виджета с настройкой заголовка

Рассмотрим пример создания простого виджета, который выводит на сайт заголовок и произвольный текст, который можно задать в настройках.

class WPFreeCourses_Widget extends WP_Widget {
    public function __construct() {
        parent::__construct(
            'wpfreecourses_widget',
            __('WPFreeCourses: Простой виджет', 'wpfreecourses'),
            array('description' => __('Простой виджет с заголовком и текстом', 'wpfreecourses'))
        );
    }

    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'];
        }
        if (!empty($instance['content'])) {
            echo '<p>' . esc_html($instance['content']) . '</p>';
        }
        echo $args['after_widget'];
    }

    public function form($instance) {
        $title = !empty($instance['title']) ? $instance['title'] : '';
        $content = !empty($instance['content']) ? $instance['content'] : '';
        ?>
        <p>
            <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php _e('Заголовок:', 'wpfreecourses'); ?></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('content')); ?>"><?php _e('Текст:', 'wpfreecourses'); ?></label>
            <textarea class="widefat" id="<?php echo esc_attr($this->get_field_id('content')); ?>" name="<?php echo esc_attr($this->get_field_name('content')); ?>"><?php echo esc_textarea($content); ?></textarea>
        </p>
        <?php
    }

    public function update($new_instance, $old_instance) {
        $instance = array();
        $instance['title'] = sanitize_text_field($new_instance['title']);
        $instance['content'] = sanitize_textarea_field($new_instance['content']);
        return $instance;
    }
}

function wpfreecourses_register_widget() {
    register_widget('WPFreeCourses_Widget');
}
add_action('widgets_init', 'wpfreecourses_register_widget');

Расширяем виджет: добавляем дополнительные настройки и вывод данных из базы

Теперь, когда базовый виджет готов, можно добавить более интересный функционал. Например, вывести список последних записей из определённой категории, заданной в настройках виджета.

Для этого в форме настроек добавим выпадающий список с категориями, в методе widget() сделаем запрос к базе и выведем заголовки.

Добавление выбора категории в настройки виджета

В методе form() получаем список категорий и создаём <select>:

public function form($instance) {
    $title = !empty($instance['title']) ? $instance['title'] : '';
    $category = !empty($instance['category']) ? $instance['category'] : 0;
    $categories = get_categories(array('hide_empty' => false));
    ?>
    <p>
        <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php _e('Заголовок:', 'wpfreecourses'); ?></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('Категория:', 'wpfreecourses'); ?></label>
        <select class="widefat" id="<?php echo esc_attr($this->get_field_id('category')); ?>" name="<?php echo esc_attr($this->get_field_name('category')); ?>">
            <option value="0" <?php selected($category, 0); ?>><?php _e('Все категории', 'wpfreecourses'); ?></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>
    <?php
}

Вывод последних постов из выбранной категории

В методе widget() делаем WP_Query с параметром категории и выводим список:

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 = !empty($instance['category']) ? intval($instance['category']) : 0;
    $query_args = array(
        'posts_per_page' => 5,
        'post_status' => 'publish'
    );
    if ($category) {
        $query_args['cat'] = $category;
    }
    $query = new WP_Query($query_args);
    if ($query->have_posts()) {
        echo '<ul>';
        while ($query->have_posts()) {
            $query->the_post();
            echo '<li><a href="' . esc_url(get_permalink()) . '">' . esc_html(get_the_title()) . '</a></li>';
        }
        echo '</ul>';
        wp_reset_postdata();
    } else {
        echo '<p>' . __('Записей не найдено.', 'wpfreecourses') . '</p>';
    }
    echo $args['after_widget'];
}

Советы по безопасности и производительности при создании виджетов

При разработке виджетов очень важно учитывать безопасность и оптимизацию:

  • Используйте функции очистки данныхsanitize_text_field(), esc_html(), esc_attr(), esc_textarea() для обработки входных и выходных данных.
  • Минимизируйте количество запросов к базе. Кешируйте результаты, если виджет часто вызывается на странице.
  • Избегайте выполнения тяжёлых операций в методе widget(), чтобы не замедлять загрузку страницы.
  • Обрабатывайте ошибки и отсутствующие данные корректно, чтобы не ломать отображение сайта.

Пример кеширования вывода виджета

Можно использовать транзиенты для кеширования вывода. В widget() добавим:

public function widget($args, $instance) {
    echo $args['before_widget'];
    $cache_key = 'wpfreecourses_widget_cache_' . md5(serialize($instance));
    $output = get_transient($cache_key);
    if ($output === false) {
        ob_start();
        if (!empty($instance['title'])) {
            echo $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title'];
        }
        // вывод списка постов (как в предыдущем примере)
        // ...
        $output = ob_get_clean();
        set_transient($cache_key, $output, 3600); // кеш 1 час
    }
    echo $output;
    echo $args['after_widget'];
}

Популярные плагины для расширения функционала виджетов в WordPress

Если создание собственного виджета кажется сложным или нужно быстро добавить популярный функционал, можно использовать готовые плагины:

  • Widget Options — расширенные настройки виджетов, управление отображением по страницам и устройствам;
  • Custom Sidebars — позволяет создавать неограниченное количество сайдбаров и назначать их на разные страницы;
  • Black Studio TinyMCE Widget — виджет с визуальным редактором для добавления произвольного контента;
  • SiteOrigin Widgets Bundle — набор разнообразных виджетов с возможностью кастомизации.

Эти плагины помогут быстро получить нужный функционал без программирования, однако создание собственного виджета — это всегда гибкий и эффективный способ контролировать поведение сайта.

Оптимальное использование Transients API в WordPress для кеширования данных
12.12.2025
Безопасное удаление старого кода и функций из WordPress
15.02.2026
Автоматическое отображение подсказок в WordPress с помощью пользовательского кода и плагинов
22.01.2026
Как создать уникальные заголовки и мета описания в WordPress для улучшения SEO
15.04.2026
Как создать автоматический импорт курсов в WordPress для образовательного сайта
04.01.2026