Выпуск 23. Базовый класс для WordPress-плагина
Плагины в WordPress'е
Вы уже знаете, что плагины бывают разными. Их условно можно разделить на несколько групп. Прежде всего, это плагины-функции. То есть в файле плагина просто находится несколько функций, которые необходимо явно прописывать в шаблоне.
Следующая группа является разновидностью предыдущей - это теже плагины-функции, только "вешающие" себя на какое-либо событие (action, hook) WordPress.
Третья группа самая сложная - плагины с управлением через админ-панель. Это самые сложные в написании плагины и именно о них мы сейчас и поговорим.
Сразу предупреждаю, что материал довольно тяжел и рассчитан на подготовленного читателя.
Плагины с управлением через админ-панель
Чтобы написать такой плагин потребуется решить сразу множество задач. Помимо непосредственного подключения плагина к админ-панели, нужно обеспечить еще и функциональность плагина, например обновление каких-либо опций.
Отчасти WordPress предоставляет в распоряжение разработчика несколько функций, но на их базе полноценного управления плагина просто не создать. Когда я рассказывал о b2evolution, то отметил, как в этом "движке" красиво реализована поддержка плагинов. Для этого используется php-класс, в котором уже присутствуют базовые и необходимые функции для работы любого плагина. В этом классе (class Plugin) присутствуют название плагина, его описание, подключение в админ-панель, а также заложены функции-"пустышки", которые можно расширить для собственной обработки данных.
С WordPress'ом ситуация несколько сложнее: по сути, на откуп разработчика отдано абсолютно всё, что касается плагина.
По этой причине мы постоянно сталкиваемся с некорректной работой множества плагинов. Разработчик сам решает, каким образом ему подключать этот плагин, как он будет обрабатывать данные и т.д., и т.п.
Если бы речь шла только об одном-единственом плагине, то действительно, можно было бы поступиться "красотой" кода и сделать "главное, чтобы работало". Я и сам примерно также поступал.
Но, когда своих плагинов становится много, сталкиваешься с проблемой их поддержки, да и многие куски кода повторяются, что уже просто нерационально.
Таким образом я решил реализовать очень простой php-класс (class) и на его примере показать, что создать плагин для WordPress не так уж и сложно.
Идеи
Прежде, чем приступать непосредственно к кодированию, нужно понять, что же должен делать наш плагин. Поскольку мы делаем тестовый плагин, то мы не будем снабжать его какими-то функциями по обработке данных (только принцип "отправил/получил"). Я хочу просто показать, что для чего нужно, а вы уже по своему усмотрению сможете его модифицировать.
Итак, наш плагин должен:
- Иметь заголовок, описание.
- Должен быть добавлен в меню админ-панели.
- Уметь выполнять какие-либо действия при своей активации/деактивации.
- Уметь отображать форму данных.
- Уметь обрабатывать полученные данные из формы.
Думаю, что это минимальная функциональность любого плагина.
Файлы
Поскольку мы будем делать некий "каркас" для ваших будущих плагинов, то есть смысл сразу разделить плагин как минимум на две части. Первый файл будет подключаться к WordPress, то есть именно его WordPress и будет включать как плагин. Второй файл будет подключаться к первому и в нем мы будем реализовывать функциональность (через php-класс).
Я буду подробно останавливаться на каждом шаге - рассылка-то учебная.
![]()
Кроме этого, такое разделение позволит вынести некоторые настройки в первый файл: в дальнейшем их очень просто можно будет изменить.
Структура
Начнем с соглашения об именах файлов. Поскольку плагин я пишу для своего сайта, то и в названии будет присутствовать его адрес
. Получаем такую структуру:
.../wp-content/plugins/maxsite-org/base-plugin.php .../wp-content/plugins/maxsite-org/base-plugin.class.php
Файл "base-plugin.php"
В нем мы должны указать WordPress'у, что этот файл плагин. Делается это очень просто - дописываем в начало файла служебную информацию:
<?php /* Plugin Name: MAX: base plugin class Plugin URI: http://maxsite.org/ Description: Base plugin class Author: MaxSite.org Version: 1.0 Author URI: http://maxsite.org/ */
Далее мы должны подключить наш php-класс (мы его еще не сделали):
include_once( 'base-plugin.class.php' );
И после этого, сделать экземпляр этого класса:
$my_plugin = new maxsite_plugin_base();
Пока этого достаточно. Переходим к созданию класса.
Файл "base-plugin.class.php"
Я сразу привожу "каркас" нужного нам класса, а после объясню что и для чего нужно.
<?php
class maxsite_plugin_base
{
var $page_title;
var $menu_title;
var $access_level;
var $add_page_to;
var $short_description;
function maxsite_plugin_base()
{
$this->get_options();
}
function get_options()
{
}
function add_admin_menu()
{
}
function activate()
{
}
function deactivate()
{
}
function admin_page()
{
}
function view_options_page()
{
}
} // class
?>
Теперь объяснение.
Здесь мы объявили класс maxsite_plugin_base (в первом файле мы именно его экземпляр создали, посмотрите).
В начале мы объявляем переменные (var). Они нужны нам как дополнительные настройки:
- $page_title - название плагина
- $menu_title - название пункта меню
- $access_level - уровень доступа к плагину (0-9)
- $add_page_to - в какой закладке отображать плагин
- $short_description - короткое описание
Думаю понятно.
В PHP принято, что функция класса, совпадающая по названию с названием самого класса будет являться конструктором, и автоматически выполняться при создании экземпляра класса. В нашем случае это будет функция maxsite_plugin_base(). В ней мы прописали вызов единственной функции (get_options()), которая будет считывать опции для нашего плагина (сама функция будет пустой, поскольку наш плагин не имеет своих опций).
В принципе можно и не делать это через дополнительную функцию, однако на практике приходится выполнять несколько разных действий для инициализации плагина, например дополнительно считать опции, данные из базы данных и т.д. Поэтому проще разнести эти действия по функциям и указать их в конструкторе.
Теперь коротко о том, какие функции нам для чего нужны.
Функции коротко
function add_admin_menu()
Здесь мы подключим наш плагин к админ-панели. Нам нужно вывести пункт меню, задать уровень доступа и указать закладку.
function activate()
Функция будет выполняться при активации плагина. Это происходит, когда пользователь выбирает "активировать" плагин.
function deactivate()
Функция будет выполняться при деактивации плагина.
function admin_page()
Основная функция, которая будет обеспечивать работу плагина.
function view_options_page()
Скорее вспомогательная функция. На неё мы возложим задачу простого отображения формы.
function add_admin_menu()
Для того, чтобы добавить плагин к админ-панели, WordPress предоставляет в наше распоряжение несколько функций. Например, для того, чтобы добавить в закладку "Настройки", нужно использовать функцию add_options_page и т.п.
Синтаксис довольно простой:
function add_options_page(название, меню, доступ, __FILE__, главная функция);
Вы помните про переменную $add_page_to, которая служит для определения закладки? Именно она и укажет куда нужно добавлять плагин. Если её значение будет равно 1, то добавим в главное меню; 2 - в меню настройки; 3 - в управление; 4 - в шаблоны.
В итоге у нас получается такая функция:
function add_admin_menu()
{
if ( $this->add_page_to == 1 )
add_menu_page($this->page_title,
$this->menu_title, $this->access_level,
__FILE__, array($this, 'admin_page'));
elseif ( $this->add_page_to == 2 )
add_options_page($this->page_title,
$this->menu_title, $this->access_level,
__FILE__, array($this, 'admin_page'));
elseif ( $this->add_page_to == 3 )
add_management_page($this->page_title,
$this->menu_title, $this->access_level,
__FILE__, array($this, 'admin_page'));
elseif ( $this->add_page_to == 4 )
add_theme_page($this->page_title,
$this->menu_title, $this->access_level,
__FILE__, array($this, 'admin_page'));
}
Надеюсь, что код не очень сложный. В частности мы просто проверяем значение переменной и вызываем соответствующую функцию.
Запись $this->... означает, что нужно взять переменную или функцию из этого же класса.
Обратите внимание на указание "главной" функции класса. Для того, чтобы WordPress корректно её принял, нужно передавать её как массив: array($this, 'admin_page'), где: $this - это указание на текущий класс, а 'admin_page' - название функции (передается как строка!).
Саму же фукнцию admin_page мы уже предусмотрели раньше.
Функции activate() и deactivate()
Эти функции мы не будем заполнять (оставим пустыми), поскольку нашему плагину просто не нужна такая функциональность.
function admin_page()
Главная функция плагина. После того, как будет создан класс, управление перейдет к функции admin_page(). То есть если вы просто переходите по ссылке в меню на плагин, будет срабатывать эта функция. Точно также: когда вы будете обновлять данные (опции) плагина, то именно эта функция будет обрабатывать получаемые данные.
Пока, что нам нужно просто отобразить страницу плагина. Для этого мы создадим html-вывод.
function admin_page()
{
echo <<<EOF
<div class="wrap">
<h2>{$this->page_title}</h2>
<p>{$this->short_description}</p>
EOF;
}
Поскольку такая форма записи не очень часто встречается, то расскажу о ней.
Если мы сразу выводим текст в браузер (через echo), то пишем:
echo <<<EOF любой html-код для вывода EOF;
Символы <<< указывают PHP, что нужно выводить текст, как-будто бы он заключен в двойные кавычки "". Символ EOF служит "ограничителем" такого вывода: PHP будет воспринимать вывод до завершающего EOF;. Вы можете использовать другие символы.
Вместо echo можно использовать любую строковую переменную.
В самом же тексте вывода можно использовать, как обычно, php-переменные. Для того, чтобы избежать неопределеностей, нужно экранировать их фигурными скобками. Вот так:
{$this->short_description}
Сейчас наша функция просто выводит заголовок и короткое описание плагина. К функции view_options_page мы еще подойдем, а пока вернемся к файлу base-plugin.php
Настраиваем "base-plugin.php"
На самом деле, основной функционал мы уже написали. Теперь нам нужно добавить настройки и можно активировать плагин.
Я сразу привожу готовый код, который нужно добавить в файл "base-plugin.php" (после $my_plugin = new maxsite_plugin_base();):
// путь к плагину
$path_to_php_file_plugin = 'maxsite-org/base-plugin.php';
$my_plugin->page_title = 'Название плагина'; // название
$my_plugin->menu_title = 'Мой плагин'; // название в меню
$my_plugin->short_description = 'Описание плагина. Коротко';
$my_plugin->access_level = 5; // уровень доступа
// 1=главное меню 2=настройки 3=управление 4=шаблоны
$my_plugin->add_page_to = 1;
add_action('admin_menu', array($my_plugin, 'add_admin_menu'));
add_action('deactivate_' . $path_to_php_file_plugin,
array($my_plugin, 'deactivate'));
add_action('activate_' . $path_to_php_file_plugin,
array($my_plugin, 'activate'));
Думаю, что здесь особых вопросов не возникнет, поскольку я оставил комментарии. Остановлюсь только на add_action. Эта функция (hook, фильтр) подключает вашу функцию к другой функции WordPress'а.
Например строчка:
add_action('admin_menu', array($my_plugin, 'add_admin_menu'));
заставит WordPress после отработки функции (своей) admin_menu, выполнить нашу add_admin_menu.
Помните, что функции класса нужно передавать как массив.
С активацией и деактивацией плагина несколько сложней. Для этих целей WordPress создает hook с именем, начинающемся с activate_ плюс путь к плагину. Из-за этого мы и ввели переменную $path_to_php_file_plugin.
Собственно уже на этом этапе мы можем проверить работоспособность нашего плагина. Зайдите в админ-панель и активируйте его. У вас должен появиться пункт меню "Мой плагин".
Функция view_options_page()
Теперь давайте заставим наш плагин выполнять какие-нибудь действия. В частности он должен вывести html-форму, а после её отправки отобразить измененные параметры.
Для отображения самой формы, мы ввели функцию view_options_page(). Все, что в ней делается, так это только осуществляется отображение формы.
function view_options_page()
{
echo <<<EOF
<h3>Опции</h3>
<p>Отметьте нужные опции</p>
<form action="" method="POST">
<input type="submit" name="UPDATE" value="Готово"><br /><br />
<input type="checkbox" name="cb_ids[]" value="1"> 1<br />
<input type="checkbox" name="cb_ids[]" value="2"> 2<br />
<input type="checkbox" name="cb_ids[]" value="3"> 3
<hr />
<input type="radio" name="ra_ids[]" value="1"> 1<br />
<input type="radio" name="ra_ids[]" value="2"> 2<br />
<input type="radio" name="ra_ids[]" value="3"> 3
<hr />
1. <textarea style="height: 50px;" cols="80"
name="ta_ids[]"></textarea><br />
2. <textarea style="height: 50px;" cols="80"
name="ta_ids[]"></textarea><br />
3. <textarea style="height: 50px;" cols="80"
name="ta_ids[]"></textarea>
<hr />
1. <input type="text" name="tx_ids[]" size="10" value=""><br />
2. <input type="text" name="tx_ids[]" size="10" value=""><br />
3. <input type="text" name="tx_ids[]" size="10" value="">
<br /><br />
<input type="submit" name="UPDATE" value="Готово">
</form>
EOF;
}
В этой форме я указал по три элемента чекбоксов (checkbox), переключателей (radio), текстовых полей (text) и многострочных полей (textarea). Сделал я так много намеренно, поскольку хотел продемонстрировать принцип написания такой формы, а также её последующую обработку.
Прежде всего обратите внимание на параметры name. Вместо того, чтобы указывать уникальные имена, мы используем массив. В дальнейшем, при обработке данных, можно "пройтись" по этому массиву и получить все нужные значения. Если же вас не устраивает такой подход, то вы можете использовать обычное присваивание имен всем элементам формы. Это не принципиально.
Подходим к последнему шагу: обработаем отправленые данные.
Функция "admin_page()"
Вы помните, что WordPress будет выполнять "главную" функцию. В нашем случае это admin_page. Поэтому обработчик формы мы должны поместить именно в неё.
function admin_page()
{
echo <<<EOF
<div class="wrap">
<h2>{$this->page_title}</h2>
<p>{$this->short_description}</p>
EOF;
if (isset($_POST['UPDATE'])) { ### обновление
echo "<div class='updated'>Обновлено!</div><p>";
if (isset($_POST['cb_ids'])) { ## checkbox
foreach ($_POST['cb_ids'] as $id) {
echo 'Вы отметили checkbox: ' . $id . '<br />';
}
}
if (isset($_POST['ra_ids'])) { ## radio
foreach ($_POST['ra_ids'] as $id) {
echo 'Вы отметили radio: ' . $id . '<br />';
}
}
if (isset($_POST['ta_ids'])) { ## textarea
foreach ($_POST['ta_ids'] as $id) {
if ( strlen($id)>0 )
echo 'Вы отметили textarea: ' . $id . '<br />';
}
}
if (isset($_POST['tx_ids'])) { ## text
foreach ($_POST['tx_ids'] as $id) {
if ( strlen($id)>0 )
echo 'Вы отметили text: ' . $id . '<br />';
}
}
echo '</p>';
} // обновление
else $this->view_options_page();
echo '</div>';
}
Сами данные мы получаем через глобальный массив $_POST. В нем мы проверяем существование данных (isset) и, если они есть, проходимся по массиву с помощью foreach. Для текстовых полей, которые могут возвращать пустые строки, я дополнительно ввел проверку на длину строки (strlen).
Проверяем
Вот, собственно и всё.
Теперь, если отметить разные опции или ввести текст, наш плагин выведет нужное сообщение. Для вашего плагина наверняка потребуется написать другой обработчик, который будет выполнять какие-то полезные действия, но это, как говорится, уже другая история.
Для тех же, кто совсем запутался, я выложил для скачивания архив с готовым примером (1Кб).
Постоянная ссылка: http://maxsite.org/?p=185
Версия для печати
RSS: Выпуск 23. Базовый класс для WordPress-плагина

