В этой статье мы подробно разберем, как создать собственный виджет в WordPress с нуля. Создание виджетов позволяет расширять функциональность сайта и добавлять уникальные блоки с нужным контентом на боковые панели и другие области, поддерживающие виджеты. Мы рассмотрим структуру виджета, регистрацию, вывод на сайте, а также добавим настройки, чтобы вы могли легко адаптировать пример под свои задачи.
Что такое виджет в WordPress и зачем создавать свой
Виджет — это независимый блок контента или функционала, который пользователь может добавить в боковую панель (sidebar) или другую область темы. Встроенные виджеты WordPress покрывают базовые задачи: поиск, категории, последние записи и т.д. Однако часто требуется что-то более специфичное — например, вывод уникальной информации, формы подписки, произвольный HTML с динамическими данными.
Создание собственного виджета даёт полный контроль над его поведением и выводом. Вы сможете реализовать любые идеи, не ограничиваясь стандартным функционалом, а также легко переиспользовать код на разных проектах.
Далее мы рассмотрим, как зарегистрировать и создать виджет на основе класса, который наследуется от WP_Widget.
Регистрация и базовая структура виджета WordPress
Каждый виджет — это класс PHP, который наследуется от WP_Widget. Для начала создадим минимальный класс виджета и зарегистрируем его в системе.
class Wpma_Custom_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'wpma_custom_widget', // ID виджета
'WPMA: Пользовательский виджет', // Название
array('description' => 'Пример собственного виджета WPMA')
);
}
public function widget($args, $instance) {
echo $args['before_widget'];
echo '<p>Это мой первый виджет WPMA!</p>';
echo $args['after_widget'];
}
public function form($instance) {
// Здесь будет форма настроек виджета
}
public function update($new_instance, $old_instance) {
// Сохраняем настройки
return $new_instance;
}
}
function wpma_register_custom_widget() {
register_widget('Wpma_Custom_Widget');
}
add_action('widgets_init', 'wpma_register_custom_widget');Здесь мы создали класс Wpma_Custom_Widget, который выводит простой текст, и зарегистрировали его с помощью хука widgets_init. Если добавить этот код в файл functions.php вашей темы или в плагин — виджет появится в админке.
Добавление настроек в виджет: параметры и сохранение
Чтобы виджет был удобным, нужно добавить параметры, которые пользователь сможет менять через админку. В методе form() рисуем форму настроек, а в update() сохраняем их.
Добавим поле для заголовка и текста:
public function form($instance) {
$title = !empty($instance['title']) ? $instance['title'] : '';
$text = !empty($instance['text']) ? $instance['text'] : '';
?>
<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('text'); ?>">Текст:</label>
<textarea class="widefat" id="<?php echo $this->get_field_id('text'); ?>" name="<?php echo $this->get_field_name('text'); ?>" rows="4"><?php echo esc_textarea($text); ?></textarea>
</p>
<?php
}
public function update($new_instance, $old_instance) {
$instance = array();
$instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
$instance['text'] = (!empty($new_instance['text'])) ? sanitize_textarea_field($new_instance['text']) : '';
return $instance;
}Теперь в виджете можно задать заголовок и произвольный текст. В методе widget() выведем их:
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['text'])) {
echo '<p>' . esc_html($instance['text']) . '</p>';
}
echo $args['after_widget'];
}Пример расширенного виджета: вывод последних постов с кастомными параметрами
Рассмотрим пример виджета, который выводит последние записи с возможностью указать количество постов и категорию.
Добавим в форму настройки поле для количества и выбора категории:
public function form($instance) {
$title = !empty($instance['title']) ? $instance['title'] : '';
$number = !empty($instance['number']) ? absint($instance['number']) : 5;
$category = !empty($instance['category']) ? $instance['category'] : '';
$categories = get_categories();
?>
<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 id="<?php echo $this->get_field_id('number'); ?>" name="<?php echo $this->get_field_name('number'); ?>" type="number" value="<?php echo esc_attr($number); ?>" min="1" max="20" style="width: 50px;" />
</p>
<p>
<label for="<?php echo $this->get_field_id('category'); ?>">Категория:</label>
<select id="<?php echo $this->get_field_id('category'); ?>" name="<?php echo $this->get_field_name('category'); ?>" class="widefat">
<option value="">Все категории</option>
<?php foreach ($categories as $cat) : ?>
<option value="<?php echo $cat->slug; ?>" <?php selected($category, $cat->slug); ?>><?php echo esc_html($cat->name); ?></option>
<?php endforeach; ?>
</select>
</p>
<?php
}
public function update($new_instance, $old_instance) {
$instance = array();
$instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
$instance['number'] = (!empty($new_instance['number'])) ? absint($new_instance['number']) : 5;
$instance['category'] = (!empty($new_instance['category'])) ? sanitize_text_field($new_instance['category']) : '';
return $instance;
}В методе widget() сделаем запрос и выведем список постов:
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'];
}
$query_args = array(
'post_type' => 'post',
'posts_per_page' => !empty($instance['number']) ? $instance['number'] : 5,
);
if (!empty($instance['category'])) {
$query_args['category_name'] = $instance['category'];
}
$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()) . '">' . get_the_title() . '</a></li>';
}
echo '</ul>';
} else {
echo '<p>Посты не найдены.</p>';
}
wp_reset_postdata();
echo $args['after_widget'];
}Рекомендации и лучшие практики при создании виджетов
При разработке виджетов важно соблюдать несколько правил:
- Используйте префиксы в именах классов и функций, чтобы избежать конфликтов (как мы сделали с
Wpma_). - Обрабатывайте пользовательский ввод через функции безопасности:
esc_html,esc_attr,sanitize_text_fieldи др. - Не забывайте использовать
wp_reset_postdata()после кастомных запросовWP_Query, чтобы не нарушить глобальный цикл. - Предоставляйте понятный интерфейс настроек с понятными подписями.
- Тестируйте ваш виджет на разных темах и с разными плагинами, чтобы избежать конфликтов.
Полезные плагины для работы с виджетами WordPress
Если вы хотите расширить возможности виджетов без программирования, обратите внимание на следующие плагины:
- Widget Options — добавляет расширенные настройки виджетов, например, управление отображением по страницам, ролям пользователей.
- Custom Sidebars — позволяет создавать собственные боковые панели и назначать их на разные страницы.
- Black Studio TinyMCE Widget — расширяет стандартный текстовый виджет редактором TinyMCE, что упрощает форматирование.
Однако для уникального функционала лучше создавать собственные виджеты, как мы рассмотрели.