Как создать собственный виджет в WordPress

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

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

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

В этой статье мы подробно разберем, как сделать собственный виджет в WordPress, который можно использовать в теме или плагине, рассмотрим структуру кода и разберем примеры.

Как работает система виджетов в WordPress

В WordPress виджеты реализованы как классы, наследующиеся от базового класса WP_Widget. Такой подход позволяет удобно создавать кастомные виджеты с методами для вывода, настройки и обработки данных.

Основные методы, которые нужно реализовать в собственном виджете:

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

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

Пример: создание виджета "WPManual Последние записи"

Создадим простой виджет, который выводит заданное количество последних записей. Пользователь сможет указать заголовок и количество постов.

Вставьте следующий код в файл functions.php вашей темы или в файл плагина:

class WPManual_Widget_Recent_Posts extends WP_Widget {
    public function __construct() {
        parent::__construct(
            'wpmanual_recent_posts', // ID виджета
            'WPManual Последние записи', // Название
            array('description' => 'Выводит последние записи с настройками')
        );
    }

    public function widget($args, $instance) {
        echo $args['before_widget'];

        $title = apply_filters('widget_title', $instance['title']);
        $number = !empty($instance['number']) ? absint($instance['number']) : 5;

        if ($title) {
            echo $args['before_title'] . $title . $args['after_title'];
        }

        $recent_posts = new WP_Query(array(
            'posts_per_page' => $number,
            'post_status' => 'publish'
        ));

        if ($recent_posts->have_posts()) {
            echo '<ul>';
            while ($recent_posts->have_posts()) {
                $recent_posts->the_post();
                echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
            }
            echo '</ul>';
        } else {
            echo '<p>Нет записей</p>';
        }

        wp_reset_postdata();

        echo $args['after_widget'];
    }

    public function form($instance) {
        $title = isset($instance['title']) ? $instance['title'] : 'Последние записи';
        $number = isset($instance['number']) ? absint($instance['number']) : 5;
        ?>
        <p>
            <label for="<?php echo $this->get_field_id('title'); ?>">Заголовок:</label>
            <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>"
                   name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($title); ?>">
        </p>
        <p>
            <label for="<?php echo $this->get_field_id('number'); ?>">Количество записей:</label>
            <input class="tiny-text" id="<?php echo $this->get_field_id('number'); ?>"
                   name="<?php echo $this->get_field_name('number'); ?>" type="number" step="1" min="1" value="<?php echo esc_attr($number); ?>" size="3">
        </p>
        <?php
    }

    public function update($new_instance, $old_instance) {
        $instance = array();
        $instance['title'] = (!empty($new_instance['title'])) ? sanitize_text_field($new_instance['title']) : '';
        $instance['number'] = (!empty($new_instance['number'])) ? absint($new_instance['number']) : 5;
        return $instance;
    }
}

function wpmanual_register_widgets() {
    register_widget('WPManual_Widget_Recent_Posts');
}
add_action('widgets_init', 'wpmanual_register_widgets');

Регистрация и активация виджета

Чтобы виджет появился в списке доступных, он должен быть зарегистрирован функцией register_widget. В примере выше это сделано в функции wpmanual_register_widgets, которая подключена к хуку widgets_init.

После добавления кода в тему или плагин зайдите в админку WordPress в раздел Внешний вид → Виджеты и найдите там «WPManual Последние записи». Добавьте его в нужную область и настройте заголовок и количество постов.

Расширение функционала виджета: добавляем вывод даты и миниатюры

Для более информативного виджета можно добавить вывод даты публикации и миниатюры записи. Это позволит пользователям быстрее ориентироваться в контенте.

Для этого модифицируем метод widget следующим образом:

public function widget($args, $instance) {
    echo $args['before_widget'];

    $title = apply_filters('widget_title', $instance['title']);
    $number = !empty($instance['number']) ? absint($instance['number']) : 5;
    $show_date = isset($instance['show_date']) ? (bool) $instance['show_date'] : false;

    if ($title) {
        echo $args['before_title'] . $title . $args['after_title'];
    }

    $recent_posts = new WP_Query(array(
        'posts_per_page' => $number,
        'post_status' => 'publish'
    ));

    if ($recent_posts->have_posts()) {
        echo '<ul>';
        while ($recent_posts->have_posts()) {
            $recent_posts->the_post();
            echo '<li>';
            if (has_post_thumbnail()) {
                echo '<div class="wpmanual-thumb">' . get_the_post_thumbnail(get_the_ID(), 'thumbnail') . '</div>';
            }
            echo '<a href="' . get_permalink() . '">' . get_the_title() . '</a>';
            if ($show_date) {
                echo ' <span class="wpmanual-date">(' . get_the_date() . ')</span>';
            }
            echo '</li>';
        }
        echo '</ul>';
    } else {
        echo '<p>Нет записей</p>';
    }

    wp_reset_postdata();

    echo $args['after_widget'];
}

Не забудьте добавить поле для настройки show_date в форму form и обработку в update. Это позволит пользователю выбирать, показывать дату или нет.

Добавление поля "Показывать дату" в форму

public function form($instance) {
    $title = isset($instance['title']) ? $instance['title'] : 'Последние записи';
    $number = isset($instance['number']) ? absint($instance['number']) : 5;
    $show_date = isset($instance['show_date']) ? (bool) $instance['show_date'] : false;
    ?>
    <p>
        <label for="<?php echo $this->get_field_id('title'); ?>">Заголовок:</label>
        <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>"
               name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($title); ?>">
    </p>
    <p>
        <label for="<?php echo $this->get_field_id('number'); ?>">Количество записей:</label>
        <input class="tiny-text" id="<?php echo $this->get_field_id('number'); ?>"
               name="<?php echo $this->get_field_name('number'); ?>" type="number" step="1" min="1" value="<?php echo esc_attr($number); ?>" size="3">
    </p>
    <p>
        <input class="checkbox" type="checkbox" <?php checked($show_date); ?> id="<?php echo $this->get_field_id('show_date'); ?>" name="<?php echo $this->get_field_name('show_date'); ?>" />
        <label for="<?php echo $this->get_field_id('show_date'); ?>">Показывать дату публикации</label>
    </p>
    <?php
}

Обработка поля show_date при сохранении

public function update($new_instance, $old_instance) {
    $instance = array();
    $instance['title'] = (!empty($new_instance['title'])) ? sanitize_text_field($new_instance['title']) : '';
    $instance['number'] = (!empty($new_instance['number'])) ? absint($new_instance['number']) : 5;
    $instance['show_date'] = isset($new_instance['show_date']) ? (bool) $new_instance['show_date'] : false;
    return $instance;
}

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

Если вы не хотите писать виджеты с нуля, можно воспользоваться готовыми решениями из репозитория плагинов. Вот несколько популярных и полезных плагинов для работы с виджетами:

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

Эти плагины помогут гибко настроить отображение и управление виджетами без необходимости писать код.

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

При разработке виджетов важно помнить о безопасности и эффективности кода. Вот несколько рекомендаций:

  • Всегда используйте функции экранирования и фильтрации входных данных (например, sanitize_text_field, esc_html, esc_url) при сохранении и выводе информации.
  • Оптимизируйте запросы к базе данных, не делайте лишних запросов внутри цикла и используйте wp_reset_postdata() после пользовательских запросов.
  • Не выводите необработанный HTML, чтобы избежать XSS-уязвимостей.
  • Следите за нагрузкой: не запрашивайте слишком много записей, добавляйте кеширование, если виджет сложный.

Соблюдение этих правил поможет сделать ваш виджет надежным и быстрым.

Итог: создание виджета — простой способ расширить функционал WordPress

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

WooCommerce: как добавить собственные поля в форму оформления заказа
28.05.2026
WooCommerce: как использовать хуки для изменения шаблонов писем
16.05.2026
Как создать собственный виджет в WordPress
03.12.2025
Как удалить пустые мета-поля в WordPress с помощью кода
12.03.2026
Как проверить и использовать активные CRON задачи в WordPress
05.02.2026