Одно из основных нововведений WordPress 2.8 это новый API для создания виджетов, делающий создание виджетов очень простым. Я расскажу, как сделать плагин добавляющий виджет на примере плагина-виджета “будущие посты”.
Для начала немного о том, как работает новый API.
Начиная с WordPress 2.8 виджет, это не просто набор функций. Виджет, это класс наследующий класс WordPress под названием WP_Widget, в php как и в любом ООП языке программирования, класс наследник получает методы класса родителя. Проще говоря в своем виджете мы можем пользоваться уже готовыми функциями написанными разработчиками Вордпресс в классе WP_Widget.
Сначала я напишу весь код плагина, а потом расскажу как он работает
<?php
/*
Plugin Name: Future Posts
*/
?>
<?
class FuturePosts extends WP_Widget {
function FuturePosts() {
parent::WP_Widget(false, $name = 'Future Posts');
}
function widget($args, $instance) {
extract( $args );
?>
<?php echo $before_title
. $instance['title']
. $after_title;
query_posts('order=ASC&post_status=future');
while (have_posts()) : the_post(); ?>
<li><?php the_title();?></li>
<?php endwhile; ?>
<?php
}
function update($new_instance, $old_instance) {
return $new_instance;
}
function form($instance) {
$title = esc_attr($instance['title']);
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
</label>
</p>
<?php
}
}
add_action('widgets_init', create_function('', 'return register_widget("FuturePosts");'));
?>
По большому счету всё поведение виджета описано в трех функциях, widget – непосредственно вывод виджета в блог, update – обновление виджета, form – форма изменения настроек виджета в панели администрирования. Найдя эти функции в вашем виджете, WordPress сам сделает остальное, выведет текст виджета в блог, запишет данные в БД, сделает форму управления виджетом. По большому счету виджету для работы достаточно функции
function widget() {
echo "Я виджет";
}
всё остальное уже сделано за нас разработчиками.
Для каждого виджета wordpress автоматически создает поле в таблице БД и записывает туда все данные о виджете, включая все переменные, отправленные через форму. Эти данные доступны в функциях плагина через массив $instance.
Рассмотрим код плагина подробно.
<?php /* Plugin Name: Future Posts */ ?>
Эта часть необходима для того, что бы WordPress понял, что файл является плагином, в Plugin Name нужно написать название нашего плагина.
class FuturePosts extends WP_Widget {
Эта строка открыавет класс нашего виджета и наследует его от WP_Widget, все функции нашего виджета будут находится в этом классе.
function FuturePosts() {
parent::WP_Widget(false, $name = 'Future Posts');
}
Функция конструктор необходимая для создания виджета, как вы наверное уже догадались, $name = ‘Future Posts’ это название нашего виджета. Название этой функции должно совпадать с названием класса.
Функция widget – непосредственно функция вывода виджета в блог. Функция выводит
заголовок, который берется из БД через массив $instance, если заголовок не определен, это не вызовет ошибок.
echo $before_title . $instance['title'] . $after_title;
а затем список постов, запрошенных при помощи стандартной функции wordpress query_posts
query_posts('order=ASC&post_status=future');
while (have_posts()) : the_post(); ?>
<li><?php the_title();?></li>
<?php endwhile; ?>
Функция update служит для обновления данных плагина, необходима, например, для валидации перед записью данных формы в БД, в нашем случае она совпадает со стандартной функцией класса.
function update($new_instance, $old_instance) {
return $new_instance;
}
Функция form является панелью управления нашим виджетом, рассмотрим подробнее, что в ней происходит
$title = esc_attr($instance['title']);
Эта строчка получает заголовок нашего виджета, если он есть в БД.
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
</label>
А дальше идет простое поле обычной HTML формы для ввода заголовка нашего виджета, если заголовок уже есть в БД он будет виден в форме. После отправки формы, заголовок будет автоматически записан в БД. Предположим, под заговоком мы хотим разместить описание виджета, достаточно добавить в форму еще одно поле для ввода описания и оно будет записано в БД при отправке формы и будет доступно, как и другие переменные виджета в массиве $instance, в том числе из функции widget.
И последний шаг, наш виджет нужно включить, для этого после класса нашего виджета находится строка указывающая на то, что наш класс “FuturePosts” необходимо зарегистрировать.
add_action('widgets_init', create_function('', 'return register_widget("FuturePosts");'));
На этом всё, в виджете можно использовать любые php и wordpress функции, например query_posts запрашивает посты вашего блога, можно выводить посты из определенной категории или например, самые комментируемые посты, функциональность ограничивается только вашей фантазией, удачи!
Вот несколько ссылок, которые помогут в создании виджетов:
Страница официальной документации по новому API
Код стандартных виджетов с использованием нового API
Код класса WP_Widget, все функции достаточно подробно описаны
Похожие посты:
23 Комментариев к статье Пишем плагин-виджет для WordPress с использованием нового Widgets API
29th Июнь 2009 в 12:47
Есть у меня мысль сделать один плагин к WP, но сам я от программирования далек.Поэтому хочу задать глупый вопрос – насколько сложно разобраться в PHP и WP API на уровне, достаточном для выполнения задуманного? Понимаю, что при желании можно все сделать, но, может будут какие-либо советы?
29th Июнь 2009 в 13:14
@Jekyll
Все зависит от того, что хотите реализовать, в принципе выше вполне рабочий плагин, можно сделать по аналогии, все функции php и wp хорошо документированны. Есть и сложные плагины, что бы такой написать нужно хорошо владеть php
30th Июнь 2009 в 12:49
Спасибо. Очень интересная статья. Надо будет попробывать сделать что нибудь.
30th Июнь 2009 в 17:04
круто)
19th Июль 2009 в 20:40
скажите, а данный плагин пишется через админку или в любом редакторе, а потом загружается.
Если загружается, то как загрузить виджет?
20th Июль 2009 в 09:17
@Илья
Илья, не очень понял, что вы хотите узнать. Вобще файл плагина загружается на сайт а потом в админке включается плагин.
1st Сентябрь 2009 в 06:43
Спасибо! Сделал свой плагин на основе Вашего примера
1st Сентябрь 2009 в 12:45
Рад что моя статья помогла!
27th Май 2010 в 09:53
Wordpresser, подскажите – как сделать так, чтоб при отключении виджета, и повторном его включении сохранялись введенные в нем ранее данные?
27th Май 2010 в 21:29
RaftKorn, вообще по идее содержимое виджета должно сохранятся, так как хранится эта информация в базе.
18th Июнь 2010 в 14:42
Помогите найти нужный плагин!!!! Нигде его не видел, уже месяц ищу…
Плагин который для каждой страницы создает виджет с html кодом конкретно для данной страницы. Я сам заполняю html для каждой страницы (ну или поста). Это нужно для того, чтобы я мог прикреплять ссылки или постовые не к посту снизу, а выводить сбоку в виджете!
Ответьте пожалуйста!!! Спасибо.
2nd Август 2010 в 17:45
Большое спасибо!
Мой первый виджет заработал!
15th Июль 2011 в 10:54
Тут еще нужно в конце добавить обязательно wp_reset_query() для того, чтобы можно было использовать Loop далее в php-файле!
27th Ноябрь 2011 в 23:00
Спасибо за статью, интересная, вот еще одна статья ( http://lifeexample.ru/php-primeryi-skriptov/pishem-plagin-wordpress.html ) о том как писать плагин для wordpressa с немного другим подходом, может кому то будет интересным.
21st Январь 2012 в 02:20
Настоятельно рекомендую всем Wordpress-разработчикам использовать режим отладки в своем _тестовом_ (дома, на localhost) сайте режим отладки. Чтоб можно было сразу видеть где вы допустили ошибку. Для этого в файле wp-config.php вставьте следующие строки:
define( ‘WP_DEBUG’, true );
define( ‘WP_DEBUG_LOG’, true );
define( ‘WP_DEBUG_DISPLAY’, true );
Думаю по названию констант и так понятно назначение этих директив.
После вкючения define( ‘WP_DEBUG’, true ); в папке wp-content создастся файл debug.log, в который буду записываться все ошибки (плагинов, тем, самого движка) вашего Wordpress сайта.
21st Январь 2012 в 02:24
P.S. Прошу прощения, debug.log создается после включения define( ‘WP_DEBUG_LOG’, true );
21st Январь 2012 в 03:35
Предлагаю поправку №1 )
В функции form() есть такая строка:
А дело в том, что как минимум 1 раз $title у вас будет пустым — при установке плагина. Так вот, чтоб не было сего досадного казуса, предлагаю вместо:
$title = esc_attr($instance['title']);
Дело в том, что когда $title пустой PHP генерирует предупреждение:
PHP Notice: Undefined index: title in wp-content/plugins/future-posts/future-posts.php
И правильно делает, что предупреждает
$title = esc_attr($instance['title']);
писать так:
if ( isset( $instance['title'] ) )
$title = esc_attr( $instance['title'] );
Если не всем понятно — это условие, дословно:
«Если $instance['title'] не пустой» (1 строчка кода),
назначить $title значение esc_attr( $instance['title'] );
Можно кстати сократить, для любителей лаконичности:
$title = (isset( $instance['title'] ) ) ? esc_attr( $instance['title'] ) : »;
Работать будет так же.
21st Январь 2012 в 03:42
P.S. Данный сайт как то странно переформатировал ДВЕ одинарные кавычки в строке:
$title = (isset( $instance['title'] ) ) ? esc_attr( $instance['title'] ) : »;
Имейте ввиду, это не «ёлочки», это _две_одинарные_кавычки_. Это важно.
21st Январь 2012 в 04:41
Поправка №2
Не знаю как у вас там, в далёком прошлом (судя по дате этого поста),
а у нас, в 2012-ом, на версии Wordpress 3.3.1 строка
query_posts(‘order=ASC&post_status=future’);
для функции widget() не работает.
Залез в базу данных, таблицу wp_posts и увидел, что статус записи регламентируется в поле post_status и отныне статус записей, которые ожидают утверждения (публикации) помечается как pending, а не future.
В итоге, чтоб всё это дело заработало в Wordpress 3.3.1 писать нужно так:
query_posts( ‘order=ASC&post_status=pending’ );
Предлагаю автору изменить и дополнить статью, руководствуясь современными реалиями и внесенными поправками
22nd Январь 2012 в 05:27
Поправка №3
В функции widget() допущена ошибка.
Код:
в итоге генерируется например в такое (смотрите HTML):
Какой то заголовок
запись № 1
запись №2
Что понятное дело не есть гуд.
А надо писать вот как:
echo the_title(», », true);
Данный код будет корректно обработан в Wordpress и на выходе вы получите код сгенерированной странички такого вида:
Какой то заголовок
запись № 1
запись №2
Разница очевидна
Описание функции the_title: http://codex.wordpress.org/Function_Reference/the_title
22nd Январь 2012 в 05:32
P.S. Автор сайта, отключи эту странную штуку, которая вырезает и изменяет код в сообщениях. В итоге весь код которыя я написал в предыдущем посте изменился, а некоторый исчез вообще.
Не интересно
22nd Январь 2012 в 06:03
Хотел ещё улучшить этот виджет, внести пару конструктивных предложений. Но не буду писать что придумал. Сайт всё равно код покоцает
22nd Январь 2012 в 16:35
Спасибо, Сергей, над комментариями поработаю.