Пишем wordpress плагин hello_world. Продолжение.
Окей, мы написали плагин для добавления “hello, world” после заголовка каждого поста. Вполне очевидным направлением для расширения функциональности этого плагина будет добавление настроек Пусть, например, мы хотим сделать возможным редактирование текста, который будет добавляться. Чтобы было не “hello, world”, а то, что мы захотим. |
Добавить такую возможность для пользователей нашего wordpress плагина можно двумя путями:
- Вынести все настройки в удобной форме в начало скрипта и прокомментировать их.
- Вынести настройки в админку wordpress`а, используя возможности его api.
С первым способом все кто php скрипты писал уже знаком Он не очень-то удобен для программ-плагинов.
Сегодня напишу про второй способ.
Для вынесения настроек wordpress плагина в админку надо сделать две вещи:
- Добавить кнопку в меню админки для настроек вашего плагина.
- Написать обработчик для этой кнопки.
Рассмотрим подробнее оба этапа.
Добавление кнопки вашего плагина в меню админки.
Меню админки wordpress`а состоит из двух уровней.
В руководстве написано, что создавать кнопку плагина в верхнем уровне стоит только, если он добавляет к wp какие-то совершенно уникальные возможности.
В принципе, наш плагин под эти требования подходит, но ради экономии места… я решил добавить его в подменю настроек
Добавление пункта в меню админки делается через функцию:
add_menu_page(page_title, menu_title, access_level/capability, file, [function]),
где
page_title – заголовок окна для вашего плагина (тоже что и поле <title> в html),
menu_title – то что будет написано на кнопке в меню,
access_level/capability – уровень доступа пользователя, у которого кнопка будет видна,
file – имя скрипта-обработчика для этой кнопки
function – фукнция-обработчик из скрипта file.
function – необязательный параметр. Если он не указан, то обработкой будет заниматься весь скрипт. Если функция указана, то для обработки будет вызываться только она (позже покажу на примере что это значит).
Добавления пункта подменю делается через другие функции.
Например,
add_submenu_page(parent, page_title, menu_title, access_level/capability, file, [function]);
Здесь появляется еще один параметр – parent, в нем будет имя файла-обработчика для кнопки верхнего меню (поле file из функции add_menu_page).
Кроме этой функции для стандартных пунктов меню верхнего уровня есть свои функции.
Для пункта настроек, например - add_options_page.
Ее как раз и будем использовать.
Добавляем наш пункт “Hello, world” в подменю настроек:
add_options_page(‘Hello world’, ‘Hello world’, 8, basename(__FILE__), ‘get_hello_form’);
Я указал уровень доступа – 8, это права админа (можно указать еще и 9-10). Чем больше уровень, тем круче должен был пользователь
Кнопку добавили. Переходим ко второму этапу.
Написание обработчика для кнопки плагина.
В качестве функции-обработчика в add_options_page я указал get_hello_form. Вот она:
if (!empty($_REQUEST['hello_text'])){
update_option('hello_text', $_REQUEST['hello_text']);
echo '<div id="message" class="updated fade"><p>Updated.</p></div>';
}
?>
<div class="wrap">
<h2>Hello world</h2>
<form method="post" action="">
<h3>Введите текст:</h3>
<input type="text" name="hello_text" value="<?php echo get_option('hello_text') ?>" /><br /><br />
<input type="submit" name="update" value="Сохранить">
</form>
</div>
<?
}
Она выводит форму, и она же ее обрабатывает (сохраняет нашу настройку).
Ах да, я забыл рассказать про механизм настроек в wordpress. Очень удобно, между прочим.
Итак, все настроки wordpress`а хранятся в БД в виде:
В первом столбце имя опции, во втором – значение.
Выбрать значение опции можно по ее имени функцией get_option():
get_option(‘option1’); // вернет “123”
Изменить значение опции можно функцией update_option:
update_option(‘option1’, ‘234’);
get_option(‘option1’); // вернет “234”
Кстати, update_option сама добавит опцию в БД если ее еще нет там.
Опцию можно также создать функцией add_option:
add_option($name, $value = ”, $deprecated = ”, $autoload = ‘yes’);
С первыми двумя параметрами понятно.
Третий – описание опции (написано, что уже не используется, но раньше там хранилось описание опции).
Четвертый ($autoload) – как я понял, указывает, будет ли ваша опция кэшироваться при запуске wordpress, чтобы каждый раз ее не брать из базы в процессе работы, или не будет.
Теперь возвращаюсь к админке. У нас есть функция-обработчик для кнопки и сама кнопка. Как теперь все это заставить работать?
Вот готовый к работе скрипт wordpress плагина hello_world:
/*
Plugin Name: Hello World
Plugin URI: https://i-novice.net/wpplugins/my_hello_world.zip
Author: Novice
Author URI: https://i-novice.net/
*/
function get_hello_form() {
if (!empty($_REQUEST['hello_text'])){
update_option('hello_text', $_REQUEST['hello_text']);
echo '<div id="message" class="updated fade"><p>Updated.</p></div>';
}
?>
<div class="wrap">
<h2>Hello world</h2>
<form method="post" action="">
<h3>Введите текст:</h3>
<input type="text" name="hello_text" value="<?php echo get_option('hello_text') ?>" /><br /><br />
<input type="submit" name="update" value="Сохранить">
</form>
</div>
<?
}
function hello_admin_menu(){
add_options_page('Hello world', 'Hello world', 8, basename(__FILE__), 'get_hello_form');
}
function hello_world($title) {
echo $title.' -> '.get_option('hello_text');
}
add_filter('the_title', 'hello_world');
add_action('admin_menu', 'hello_admin_menu');
?>
Итак, это скрипт для плагина hello_world, с возможностью настройки через админку. И он написан неправильно
Сейчас объясню почему.
Вернемся к функции обработки get_hello_form.
Сначала она проверяет, не произошло ли обновление параметров (сабмит формы). Если да, то обновляет опцию в БД и выводит сообщение (“Updated”). Потом она выводит форму.
По сути, единственное, что она делает - это обновляет опции.
А для таких форм в wordpress есть собственные, уже готовые механизмы обработки.
Реализуются они так:
?>
<div class="wrap">
<h2>Hello world</h2>
<form method="post" action="options.php">
<?php wp_nonce_field('update-options'); ?>
<h3>Введите текст:</h3>
<input type="text" name="hello_text" value="<?php echo get_option('hello_text') ?>" /><br /><br />
<input type="hidden" name="action" value="update" />
<input type="hidden" name="page_options" value="hello_text" />
<input type="submit" name="update" value="Сохранить">
</form>
</div>
<?
}
Данные формы передаются скрипту options.php методом POST:
<form method=”post” action=”options.php”>
После этой строки нужно вставить вызов функции wp_nonce_field() :
<?php wp_nonce_field(‘update-options’); ?>
Она добавит несколько скрытых полей в форму, которые нужны скрипту options.php, чтобы понять какой модуль к нему обращается и т.д. (служебные поля короче ).
После перечисления всех своих полей внутри формы нужно добавить еще два служебных поля:
<input type=”hidden” name=”action” value=”update” />
<input type=”hidden” name=”page_options” value=”hello_text” />
Первое поле указывает скрипту options.php что нужно сделать (обновить опции).
Второе – имена опций, перечисленные через запятую (имена полей в вашей форме должны совпадать с именами опций). У меня только одно поле, поэтому без запятых обошлось.
Ну, дальше только кнопка submit и все.
В результате получаем:
/*
Plugin Name: Hello World
Plugin URI: https://i-novice.net/wpplugins/my_hello_world.zip
Author: Novice
Author URI: https://i-novice.net/
*/
function get_hello_form() {
?>
<div class="wrap">
<h2>Hello world</h2>
<form method="post" action="options.php">
<?php wp_nonce_field('update-options'); ?>
<h3>Введите текст:</h3>
<input type="text" name="hello_text" value="<?php echo get_option('hello_text') ?>" /><br /><br />
<input type="hidden" name="action" value="update" />
<input type="hidden" name="page_options" value="hello_text" />
<input type="submit" name="update" value="Сохранить">
</form>
</div>
<?
}
function hello_admin_menu(){
add_options_page('Hello world', 'Hello world', 8, basename(__FILE__), 'get_hello_form');
}
function hello_world($title) {
echo $title.' -> '.get_option('hello_text');
}
add_filter('the_title', 'hello_world');
add_action('admin_menu', 'hello_admin_menu');
?>
Теперь плагин написан правильно и готов к использованию.
Скачать его можно здесь: Плагин hello_world2.
Длинноватый получился пост, но админка без опций – не админка
Удачи в ваших экспериментах. Novice.
А как будет выглядеть плагин для вывода произвольного текста в призвольном месте?
Весьма доступно объяснил. Надо будет потренироваться как-нибудь.
хм,да прикольно) Только вот функции все не запоминаются сразу(Типа wp_nonce_field() ….
2 ert2: С произвольным текстом все понятно я думаю теперь А насчет произвольного места.. Место вывода текста определяется функцией для которой фильтр добавляется. Эти функции можно посмотреть в документации или в самих шаблонах wordpress`а.
да кстате твой плагин не пашет вылазиет ошибка
Parse error: syntax error, unexpected $end in Z:\home\localhost\www\wordpress\wp-content\plugins\hello_world.php on line 16
Проверил залитую версию. Все работает. Судя по ошибке, ты удалил там лишнего
Вот смотри у меня на блоге есть мани бар, сейчас у меня под инфу отдельный ПХП, как мне сделать чтобы я туда инфу вводил через админку.
Первое что в голову приходит - это сохранять текст мани бара в виде опции. У меня в плагине hello_world2 это делается через админку. А в шаблоне где у тебя выводится мани бар сделать вывод этой опции через get_option().
Ох ребят я далеко от такого знания ПХП ) Спасибо за умные слова )
хм да действительно работает я просто плагин назвал hello_world вместо hello_world2
Извиняюсь:)
А у меня возникла проблема с добавлением кнопок submenu (функция add_submenu_page()). Можно ли добавить submenu, где пункты меню ссылаются не на разные файлы, а на один, но с параметрами (типа ?page=my_plugin.php&do=action)
2 Mag: К сожалению нет. Параметр, который отвечает за линк прогоняется внутри wordpress через несколько фильтров на выходе которых остается только имя php файла. Далее оно используется как имя плагина. То есть из вашей строки:
?page=my_plugin.php&do=action wordpress будет видеть только my_plugin.
Спасибо, собственно я так и думал =)
Но вот что еще у меня получилось опытным путем. Я присваивал page разные значения. Для пункта основного меню page=my_plugin, для подменю my_plugin/item1, my_plugin/item3 и т.д. При этом меню корректно работает, я думал что мне придется заводить эти файлы в папке (item1.php, …), но получилось что работает с тем же одним my_plugin.php. Присваивая разные функции для выполнения к пунктам меню я получил нужный результат.
Вопрос, так вообще можно делать? =)
Если нет, то не подскажите как правильно.
Рекомендаций на сайте wordpress я не нашел по этому вопросу. Мне кажется что с точки зрения проектирования, лучше будет сделать один главный файл для плагина. Все функции для каждого подпункта разделить на группы и раскидать их по файлам. А потом эти файлы просто заинклудить в основной файл. Получится что все работает через один файл, но редактировать плагин в целом будет удобнее
Огромное спасибо за помощь и совет =) Опять же ещё одна ситуация, которая может возникнуть при написании плагина для WP разъяснена =) Отдельно хочу поблагодарить за статьи - ИМХО очень полезны, мне сильно помогли =)
2Mag: Спасибо
Полезная статья,спасибо но у меня вопрос к вам как в большей степени специалисту.Делаю плагин файловый менеджер на основе AjaXplorer уже все прикрутил и настроил все работает,добавил пункт в меню по нему запускаеться AjaXplorer получаеться как ссылка в меню,а как можно сделать что бы панель менеджера открывалась в админке вордпрес тоесть с меню вордпреса как все плагины?Надеюсь вы меня поняли?
2 Юрий: попробуйте открывать страницу внутри <iframe>
Спасибо.А если попробовать вызвать шапку и меню вордпрес в начале кода менеджера?Есть такая функция?
все сделал внутри , как вы писали ,впринципе пойдет.Спасибо!
Хорошие, крепкие и доступные статьи. Уверен, пригодится.
Обозначение уровня доступа типа “8” устарело, новое обозначение будет выглядеть вот так: ‘level_8′. Удачи всем!