Как написать плагин для WordPress

Опубликовано

Однажды Вы решили создать свой сайт или блог, а для системы управления Вы выбрали WordPress…Прошло время ваш сайт становится все более и более читаемым и тут, вы поняли, что для ещё большей популярности необходимо добавить немного функционала к сайту или же просто автоматизировать какое-то действие.

Вы идете на «склад» плагинов для wordpress и обнаруживаете, что необходимого плагина для Вас нету. Что же делать? Как быть ? Если вы хотя бы немного знакомы с азами программирования на php, верстке, то Вам не составит труда Самому написать плагин для WordPress.

А теперь отправимся на «кухню» для приготовления нашего плагина.

p.s. Если знаний в php и верстке нету… не расстраивайтесь, попросите кого-либо написать Вам нужный функционал 🙂

UPD: Новая статья Как написать виджет для wordpress и опубликовать в репозитории

Прежде чем начать писать плагин необходимо обратится в документацию WordPress где описаны основные принципы написания плагинов и некоторые примеры кода.

Я не буду дублировать эту информацию, а сразу перейду непосредственно к написанию кода.

Напишем простенький плагин, который позволит сохранять и выводить отзывы о Вашем сайте. Конечно, такие плагины уже есть, но для примера сойдет как раз.

Первое, что мы сделаем, это придумаем уникальное название нашему плагину — «AdvUserReviews«.

Далее создадим в директории Вашего сайта «/wp-content/plugins/» новую директорию «advuserreviews». И в ней создадим файл «advuserreviews.php». Это будет основной файл, который будет отвечать за общею инициализацию. (Желательно используйте кодировку для файлов UTF-8).

В самом начале файла необходимо указать основную информацию о плагине

<?php
/*
Plugin Name: Advanced User Reviews
Description: Отзывы о сайте
Version: 1.0
Author: Волков Вячеслав (VeXell)
Author URI: http://vexell.ru/
*/

Теперь, если перейти в панель управления, то можно увидеть, что система нашла новый плагин и предлагает его активировать. Но пока что это делать рано.

Наш новый плагин мы будем писать в стиле ООП и вся обработка данных будет находится в одном файле. Создадим основной каркас файла.

// Stop direct call
if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You are not allowed to call this page directly.'); }

if (!class_exists('AdvUserReviews')) {
class AdvUserReviews {
 // Хранение внутренних данных
 public $data = array();
  // Конструктор объекта
  // Инициализация основных переменных
  function AdvUserReviews()
  {

  }
 }
}

global $rprice;
$rprice = new AdvUserReviews();

Теперь конструктор объекта дополним следующим кодом:

function AdvUserReviews()
{
 global $wpdb;

 // Объявляем константу инициализации нашего плагина
 DEFINE('AdvUserReviews', true);

 // Название файла нашего плагина
 $this->plugin_name = plugin_basename(__FILE__);

 // URL адрес для нашего плагина
 $this->plugin_url = trailingslashit(WP_PLUGIN_URL.'/'.dirname(plugin_basename(__FILE__)));

 // Таблица для хранения наших отзывов
 // обязательно должна быть глобально объявлена перменная $wpdb
 $this->tbl_adv_reviews   = $wpdb->prefix . 'adv_reviews';

 // Функция которая исполняется при активации плагина
 register_activation_hook( $this->plugin_name, array(&$this, 'activate') );

 // Функция которая исполняется при деактивации плагина
 register_deactivation_hook( $this->plugin_name, array(&$this, 'deactivate') );

 //  Функция которая исполняется удалении плагина
 register_uninstall_hook( $this->plugin_name, array(&$this, 'uninstall') );
}

В конструкторе объекта мы используем 3 «хука» или «зацепки» (что это ?): register_activation_hook, register_deactivation_hook и register_uninstall_hook — это функции, которые выполняются при активации, деактивации плагина и его удаления соответственно.

Теперь непосредственно реализуем эти функции.

/**
 * Активация плагина
 */
function activate()
{
 global $wpdb;

 require_once(ABSPATH . 'wp-admin/upgrade-functions.php');

 $table = $this->tbl_adv_reviews;

 // Определение версии mysql
 if ( version_compare(mysql_get_server_info(), '4.1.0', '>=') ) {
  if ( ! empty($wpdb->charset) )
   $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
  if ( ! empty($wpdb->collate) )
   $charset_collate .= " COLLATE $wpdb->collate";
 }

 // Структура нашей таблицы для отзывов
 $sql_table_adv_reviews = "
	CREATE TABLE `".$wpdb->prefix."adv_reviews` (
		`ID` INT(10) UNSIGNED NULL AUTO_INCREMENT,
		`review_title` VARCHAR(255) NOT NULL DEFAULT '0',
		`review_text` TEXT NOT NULL,
		`review_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
		`review_user_name` VARCHAR(200) NULL,
		`review_user_email` VARCHAR(200) NULL,
		PRIMARY KEY (`ID`)
	)".$charset_collate.";";

 // Проверка на существование таблицы
 if ( $wpdb->get_var("show tables like '".$table."'") != $table ) {
  dbDelta($sql_table_adv_reviews);
 }

}

/**
 * Деактивация плагина
 */
function deactivate()
{
 return true;
}

/**
 * Удаление плагина
 */
function uninstall()
{
 global $wpdb;
 $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}adv_reviews");
}

Переменная $wpdb отвечает за запросы к базе Данных. Функция dbDelta анализирует текущую структуру таблицы, сравнивает ee с желаемой структурой таблицы, и либо добавляет или изменяет таблицу по мере необходимости.

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

Основная структура нового плагина готова. Теперь необходимо приступить к написанию функциональной части. Для этого в конструктор класса нам необходимо добавить следующие строчки кода:

 // Если мы в адм. интерфейсе
 if ( is_admin() ) {

  // Добавляем стили и скрипты
  add_action('wp_print_scripts', array(&$this, 'admin_load_scripts'));
  add_action('wp_print_styles', array(&$this, 'admin_load_styles'));

  // Добавляем меню для плагина
  add_action( 'admin_menu', array(&$this, 'admin_generate_menu') );

 } else {
  // Добавляем стили и скрипты
  add_action('wp_print_scripts', array(&$this, 'site_load_scripts'));
  add_action('wp_print_styles', array(&$this, 'site_load_styles'));

  add_shortcode('show_reviews', array (&$this, 'site_show_reviews'));
 }

Разберем подробнее данный участок кода. Начнем с панели администрирования.
Функция «is_admin» проверяет в каком режиме сейчас мы работаем — на сайте или в панель управления.
Далее используется несколько хуков, для функций:

  • wp_print_scripts — Добавляем необходимые javascript файлы
  • wp_print_styles — Добавляем необходимые стили
  • admin_menu — Добавляем новое меню в панели управления

Каждому хуку соответствует реализованный метод в нашем классе. В котором выполняются необходимые операции.
Рассмотрим код для подключения стилей и скриптов

/**
 * Загрузка необходимых скриптов для страницы управления
 * в панели администрирования
 */
function admin_load_scripts()
{
 // Регистрируем скрипты
 wp_register_script('advReviewsAdminJs', $this->plugin_url . 'js/admin-scripts.js' );
 wp_register_script('jquery', $this->plugin_url . 'js/jquery-1.4.2.min.js' );

 // Добавляем скрипты на страницу
 wp_enqueue_script('advReviewsAdminJs');
 wp_enqueue_script('jquery');
}

/**
 * Загрузка необходимых стилей для страницы управления
 * в панели администрирования
 */
function admin_load_styles()
{
 // Регистрируем стили
 wp_register_style('advReviewsAdminCss', $this->plugin_url . 'css/admin-style.css' );
 // Добавляем стили
 wp_enqueue_style('advReviewsAdminCss');
}

Здесь используются следующие функции.

wp_register_script — Функция служит для регистрации необходимых скриптов и последующего их подключения. Принимает несколько параметров, но основные из их них два: первый параметр — уникальный идентификатор скрипта, второй — путь к файлу скрипта. Третий параметр — зависимости данного скрипта, четвертый — версия скрипта, пятый — где размещать файл скрипта в <head> страницы или же внизу тега <body>.

wp_enqueue_script — Безопасный путь добавления JavaScript в страницу сгенерированную WordPress. Здесь стоит обратить внимание уже на зарезервированных и включенных идентификаторов скриптов в wordpress . Данная функция может принимать как один параметр — зарегистрированное название скрипта или же она может автоматически регистрировать и загружать необходимые скрипты.

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

wp_register_style — Регистрация нового стиля.
wp_enqueue_style — Добавление нового стиля.

Далее перейдем к следующему хуку — создание меню в панели администрирования.

/**
 * Генерируем меню
 */
function admin_generate_menu()
 {
  // Добавляем основной раздел меню
  add_menu_page('Добро пожаловать в модуль управления отзывами', 'Отзывы', 'manage_options', 'edit-reviews', array(&$this, 'admin_edit_reviews'));

 // Добавляем дополнительный раздел
  add_submenu_page( 'edit-reviews', 'Управление содержимом', 'О плагине', 'manage_options', 'plugin_info', array(&$this,'admin_plugin_info'));
}

Рассмотрим функции для добавления элементов меню.

add_menu_page — Добавляем основной раздел меню. Функция принимиает несколько параметров, а именно:
1 — Название новой страницы
2 — Название раздела в боковом меню
3 — Права доступа
4 — Уникальный идентификатор раздела (slug). Если же следующий параметр — функция — не будет указан, то данный параметр используется, как название вызываемого файла.
5 — Функция для отображения контента выбранной страницы.
6 — Путь к иконке
7 — Расположение в меню

add_submenu_page— Добавление дочернего элемента меню к основному. Функция по параметрам идентична предыдущей, только первым параметром передается уникальный идентификатор или slug родительской страницы.

Теперь, если зайти в панель управления, то мы увидим наше созданное меню.

Далее нам необходимо написать функции для отображения контента созданных страниц. Одна из них будет выводить просто статическую страницу (информация о плагине), другая будет показывать список отзывов и возможность их редактирования и удаления.

/**
 * Выводим список отзывов для редактирования
 */
public function admin_edit_reviews()
 {
  global $wpdb;

  $action = isset($_GET['action']) ? $_GET['action'] : null ;

  switch ($action) {

  case 'edit':
   // Получаем данные из БД
   $this->data['review'] = $wpdb->get_row("SELECT * FROM `" . $this->tbl_adv_reviews . "` WHERE `ID`= ". (int)$_GET['id'], ARRAY_A);

   // Подключаем страницу для отображения результатов
   include_once('edit_review.php');
  break;

  case 'submit':
   $inputData = array(
    'review_title' 	  => strip_tags($_POST['review_title']),
    'review_text' 	  => strip_tags($_POST['review_text']),
    'review_user_name' 	  => strip_tags($_POST['review_user_name']),
    'review_user_email'   => strip_tags($_POST['review_user_email']),
   );

   $editId=intval($_POST['id']);

   if ($editId == 0) return false;

   // Обновляем существующую запись
   $wpdb->update( $this->tbl_adv_reviews, $inputData, array( 'ID' => $editId ));

   // Показываем список отзывов
   $this->admin_show_reviews();
  break;

  case 'delete':

   // Удаляем существующую запись
   $wpdb->query("DELETE FROM `".$this->tbl_adv_reviews."` WHERE `ID` = '". (int)$_GET['id'] ."'");

   // Показываем список отзывов
   $this->admin_show_reviews();
   break;

   default:
    $this->admin_show_reviews();
  }
}

/**
 * Функция для отображения списка отзывов в адм. панели
 */
private function admin_show_reviews()
{
 global $wpdb;

 // Получаем данные из БД
 $this->data['reviews'] = $wpdb->get_results("SELECT * FROM `" . $this->tbl_adv_reviews . "`", ARRAY_A);

 // Подключаем страницу для отображения результатов
 include_once('view_reviews.php');
}

/**
 * Показываем статическую страницу
 */
public function admin_plugin_info()
{
 include_once('plugin_info.php');
}

Данный код — это основной функционал для управления отзывами на сайте. Особый интерес здесь представляют собой выполнение SQL запросов для получения, обновления и удаления данных.
Например метод $wpdb->get_row — получает одну запись, а метод $wpdb->get_results — группу записей. По умолчанию всегда возвращается объект, но передавая параметр ARRAY_A будет возвращаться массив данных. Более подробно о всех видах SQL запросов в WordPress можно прочитать тут.

Каждое действие зависит от переданного параметра «action», соответственно «edit» -редактирование отзыва, «submit» — сохранение отредактированного отзыва и «delete» — удаление отзыва.

Обмен данными со страницами отображения происходит через свойство объекта «data». Исходный код этих страниц будет выложен в архиве с данным модулем в конце статьи. Тут я их не буду вставлять, так как топик уже оказался достаточно большим.

На этом с панелью администрирования заканчиваем и переходит к отображению и добавлению отзывов со стороны пользователей.

Что бы указать wordpress, когда вызывать наш плагин, необходимо зарегистрировать «shortcode», что и было сделано в конструкторе нашего класса. Подробнее об этом написано здесь.

add_shortcode('show_reviews', array (&$this, 'site_show_reviews'));

Теперь на любой странице сайта можно разместить вот такой код [show_reviews] и это заставит выполнить указанную нами функцию (передается вторым параметром). Ниже представлен исходный код данной функции.

/**
 * Список отзывов на сайте
 */
 public function site_show_reviews($atts, $content=null)
 {
  global $wpdb;

  if (isset($_POST['action']) && $_POST['action'] == 'add-review') {
   $this->add_user_review();
  }

  // Выбираем все отзывы из Базы Данных
  $this->data['reviews'] = $wpdb->get_results("SELECT * FROM `" . $this->tbl_adv_reviews . "`", ARRAY_A);

 ## Включаем буферизацию вывода
 ob_start ();
 include_once('site_reviews.php');
 ## Получаем данные
 $output = ob_get_contents ();
 ## Отключаем буферизацию
 ob_end_clean ();

 return $output;
}

private function add_user_review()
{
 global $wpdb;

 $inputData = array(
  'review_title' 	=> strip_tags($_POST['review_title']),
  'review_text' 	=> strip_tags($_POST['review_text']),
  'review_user_name'    => strip_tags($_POST['review_user_name']),
  'review_user_email'   => strip_tags($_POST['review_user_email']),
 );

 // Добавляем новый отзыв на сайт
 $wpdb->insert( $this->tbl_adv_reviews, $inputData );
}

В принципе тут ничего сложного нету — делается SQL запрос на выборку данных, если же передан параметр «action», то сначала добавляется новый отзыв. Но стоит обратить внимание на буферизацию вывода. Она необходима для того, что бы получить данные вставляемой страницы.

Вот собственно и все. Теперь можно посмотреть, что у нас получилось. А скачать плагин и исходные коды можно вот тут.

Само собой это только пример создания плагина, но и сойдет как простая гостевушка, если ее немного доработать, например, добавить защиту от ботов и постраничный вывод. Удачного кодинга:)

Форма на сайте:

Панель управления плагином:

Редактирование отзыва:

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInShare on VK
  • Дмитрий

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

  • Дмитрий

    Здравствуйте, а то что CSS и JS файлы подключенные этим плагином выводятся на всех абсолютно страницах сайта это норма? можно сделать как то, чтобы эти файлы выводились только если на данной странице есть шорткод?

    • Дмитрий, попробуйте в функции инициализации шорткода вставить хуки по добавлению скрптов и стилей.

  • Oksana

    Эта статья — просто спасение! Спасибо большое! А не подскажете как в таком плагине можно использовать родной класс WordPress WP_List_Table?

  • Андрей Радишевський

    Здравствуйте! Подскажите пожалуйста, как можно реализовать возможность добавления отзывов с админки?

    • Виталий

      Поддерживаю
      Никак не разберусь как реализовать добавление с админки. Подключил страничку с формой отправки отзыва к админской части, но в бд ничего не добавляется…

  • Андрей

    Здравствуйте!Спасибо Вам за статью.Хотел спросить,как можно заменить стандартную форму комментариев WordPress формой,которую Вы создали? То есть например я создал какую нибудь запись,пользователь нажимает «добавить комментарий» и чтобы появилась эта форма,а не стандартная.Заранее спасибо

  • Добрый день.
    Спасибо за статью очень полезна. Еще раз для себя убедился что я не хочу разбираться с кодами.

    Я хотел бы спросить а можно ли взять плагин с ангоязычного рынка и перевести его на русский язык ?
    Сколько такое стоило бы и где лучше заказать такую услугу?

    • Здравствуйте, Роман! Для перевода на русский язык тем, плагинов и т.д. существует плагин Codestyling Localization. с его помощью можно все сделать самостоятельно и безболезненно. Мой блог: pribylwm.ru обращайтесь!

  • Александр

    Добрый вечер.
    А как вывести только за определенный месяц отзывы?

    • Александр

      разобрался

  • Иван

    Здравствуйте!
    Скопировал весь код, теперь вместо белая страница с надписью
    Parse error: syntax error, unexpected ‘public’ (T_PUBLIC) in /home/host1381575/mysite.ru/htdocs/www/wp-content/plugins/advuserreviews/advuserreviews.php on line 171

  • Сергей Лунев

    Спасибо вам за статью. Но есть одно существенное замечание — указывайте какой файл редактируем, куда «Теперь непосредственно реализуем эти функции.» где мы их б@#$ь реализуем? В этом файле, в другом, в каком месте?

    Тем не менее огромное спасибо за комментарии в коде!

  • Согласен с предыдущим комментарием — сделал один файл — не работает, скачал архив, а там несколько файлов…
    Это ладно, плагин заработал, но! при нажатии отправить он записывает в базу 3 раза один и тот же комментарий. При обновлении страницы — опять +3 коммента. В чем может быть проблема и как ее решить?

  • Ilgiz

    Это самая лучшая статья для написания плагинов! Может быть тут и присутствуют ошибки в коде, но для человека знающего PHP — это пустяк. Главное то что я прочитав свыше 100 статей, только тут понял как всё устроено.