Кратко: плагин WordPress — это папка в wp-content/plugins с PHP-файлом, в шапке которого есть заголовок Plugin Name: по нему система находит плагин и показывает его в админке. Минимальный плагин — один файл, полноценный — несколько папок, класс и страница настроек. Дальше код подключается к движку через хуки add_action и add_filter, а включение и выключение сопровождают функции активации и деактивации. Ниже — весь путь с нуля: структура, код, безопасность и проверка.
Как устроен плагин WordPress: папка, файл, заголовок
Плагин — это обычный набор файлов, который расширяет возможности WordPress, не трогая ядро и тему. Все плагины живут в одной директории — wp-content/plugins. Чтобы WordPress увидел новый плагин, достаточно создать там папку и положить в неё PHP-файл с особым комментарием-заголовком: в нём указывают название, версию, автора и лицензию.
Никакой регистрации, компиляции и сборки не нужно. Когда вы открываете раздел «Плагины» в админке, WordPress сканирует директорию, читает заголовки файлов и строит список. Отсюда главное правило: если файл с корректной шапкой лежит в wp-content/plugins, плагин уже существует — его осталось активировать.
<?php
/**
* Plugin Name: My First Plugin
* Description: Учебный плагин: добавляет пометку в подвале сайта.
* Version: 1.0.0
* Author: Ваше имя
* License: GPL-2.0-or-later
* Text Domain: my-first-plugin
*/ Сохраните этот код в файл my-first-plugin.php внутри папки wp-content/plugins/my-first-plugin — и плагин появится в списке. Активировать его можно и без админки, из командной строки: одна команда WP-CLI заменяет несколько кликов. Основные команды собраны в гайде про WP-CLI для новичков.
wp plugin activate my-first-plugin Структура плагина: какие файлы и папки завести сразу
Один файл хорош для пробы, но у растущего плагина быстро появляются свои части: код для админки, стили, переводы, служебные функции. Разложить их по папкам стоит с самого начала — через полгода вы скажете себе спасибо. Типовая структура выглядит так.
my-first-plugin/
my-first-plugin.php — главный файл с заголовком
includes/ — классы и функции
admin/ — код административной части
assets/ — CSS, JS и изображения
languages/ — файлы переводов
readme.txt — описание и история версий
uninstall.php — очистка при удалении Таблица подскажет, что где хранить и что действительно обязательно.
| Элемент | Зачем нужен | Обязателен |
|---|---|---|
| Главный PHP-файл | Заголовок плагина и точка входа, подключает остальные файлы | Да |
| includes/ | Классы, функции и интеграции — всё, что не относится к админке напрямую | По мере роста |
| admin/ | Страницы настроек, свои колонки, уведомления в админке | Если есть настройки |
| assets/ | Скрипты и стили, подключаются через wp_enqueue | Если есть интерфейс |
| languages/ | Файлы .po и .mo для переводов | Для распространения |
| readme.txt | Описание и история изменений для каталога WordPress.org | Для публикации |
| uninstall.php | Удаление опций и данных при удалении плагина | Рекомендуется |
Имя главного файла обычно повторяет имя папки: my-first-plugin/my-first-plugin.php. Тот же слаг используется как text domain — идентификатор для переводов. И сразу приучайте себя к префиксам: у всех функций плагина должно быть уникальное начало, например myfp_, иначе конфликт с чужим кодом почти неизбежен.
Несколько правил гигиены, которые сэкономят время:
- имена папок и файлов — только латиница, цифры и дефисы;
- префикс один для всего плагина, и он не должен совпадать с именами темы;
- версию храните в одном месте — в заголовке и константе;
- не смешивайте в одном файле админку и фронтенд.
Если раньше вы держали доработки в functions.php темы, есть смысл перенести функциональность в плагин: он не привязан к шаблону и переживает его обновление. Что уместно оставлять в теме, рассказано в гайде про полезные сниппеты для functions.php.
Точка входа: константы и защита от прямого доступа
PHP-файлы плагина теоретически можно открыть напрямую, минуя WordPress. Поэтому первым делом любой файл плагина проверяет константу ядра: если ABSPATH не определена, работа прекращается. Это правило номер один и для главного файла, и для каждого файла в includes.
<?php
if (!defined('ABSPATH')) {
exit;
}
define('MYFP_VERSION', '1.0.0');
add_action('wp_footer', function () {
echo '<p class="myfp-note">Работает My First Plugin</p>';
}); Константа версии пригодится для условной загрузки ресурсов: по ней браузер получает свежие файлы после обновления плагина. Обратите внимание: код начинает выполняться не сразу, а в момент, когда WordPress доходит до нужного хука. Вставлять вывод прямо в файл нельзя — к моменту его подключения страница ещё не сформирована.
Если вы сомневаетесь, где место коду — в плагине, теме или must-use расширении — сравнение ниже.
| Место | Переживает смену темы | Можно выключить | Когда выбирать |
|---|---|---|---|
| functions.php основной темы | Нет | Нет | Никогда для функциональности: правки пропадут при обновлении |
| functions.php дочерней темы | Да | Нет | Правки оформления и шаблонов |
| Обычный плагин | Да | Да | Функциональность, шорткоды, интеграции |
| mu-plugin (must-use) | Да | Нет | Служебный код, который должен работать всегда |
Как безопасно править саму тему, чтобы обновления её не затирали, мы рассказывали в статье про дочернюю тему WordPress.
Хуки: как плагин встраивается в работу движка
Плагин не вызывается сам по себе — он «подписывается» на события WordPress. За подписку отвечают две функции: add_action добавляет своё действие в точку срабатывания, а add_filter пропускает через обработчик данные и ждёт их обратно изменёнными. Первый аргумент — имя хука, второй — функция-обработчик, третий — приоритет: чем меньше число, тем раньше выполнится код.
| Хук | Когда срабатывает | Типичное применение |
|---|---|---|
| init | После загрузки ядра, до вывода страницы | Регистрация типов записей, шорткодов, переводов |
| admin_menu | При построении меню админки | Страницы настроек плагина |
| admin_enqueue_scripts | При выводе страниц админки | Стили и скрипты для настроек |
| wp_enqueue_scripts | При выводе сайта | Подключение CSS и JS фронтенда |
| the_content | При выводе содержимого записи | Пометки, кнопки, врезки в текст |
| register_activation_hook | Один раз при активации плагина | Опции по умолчанию, таблицы, правила ссылок |
| register_deactivation_hook | При деактивации плагина | Снятие запланированных задач |
Классический пример — пометка после текста записи. Фильтр the_content получает готовый HTML и возвращает его же, дополненным.
add_filter('the_content', function ($content) {
if (is_singular('post')) {
$content .= '<p class="myfp-note">Материал проверен редакцией.</p>';
}
return $content;
}); Хуки умеют не только добавлять, но и убирать чужое поведение: подписку снимает remove_action с тем же приоритетом. Так, вывод версии WordPress из шапки сайта отключается одной строкой.
remove_action('wp_head', 'wp_generator'); Заучивать список хуков не нужно: нужную точку ищут в документации или в коде ядра по шаблону do_action и apply_filters. Как устроены действия и фильтры, подробно разобрано в статье про хуки WordPress: actions и filters.
Активация и деактивация: что выполняется один раз
У плагина есть жизненный цикл: установка, активация, работа, деактивация, удаление. Активация — единственный момент, когда код выполняется гарантированно один раз. Здесь создают опции по умолчанию, вспомогательные таблицы и роли, сбрасывают правила ссылок. Подписка на событие — register_activation_hook, в колбэк приходит путь к главному файлу плагина.
register_activation_hook(__FILE__, function () {
if (false === get_option('myfp_welcome_text')) {
update_option('myfp_welcome_text', 'Спасибо за визит!');
}
flush_rewrite_rules();
}); Сброс правил ссылок нужен всем, кто регистрирует свои типы записей или адреса: без flush_rewrite_rules новые страницы будут отдавать 404, пока кто-нибудь вручную не пересохранит настройки постоянных ссылок.
Деактивация — это не удаление: плагин выключают временно, и данные должны уцелеть. Здесь корректно снять запланированные задачи и очистить временное, ничего не стирая из базы.
register_deactivation_hook(__FILE__, function () {
wp_clear_scheduled_hook('myfp_daily_sync');
}); А вот удаление — повод прибраться по-настоящему. Файл uninstall.php в корне плагина WordPress выполнит только при удалении через админку; в нём удаляют опции, таблицы и права, которые больше не нужны.
<?php
if (!defined('WP_UNINSTALL_PLUGIN')) {
exit;
}
delete_option('myfp_welcome_text'); И главное правило производительности: тяжёлые операции — создание таблиц, массовые запросы, проверка окружения — выполняются при активации, а не при каждом открытии страницы. Для повторяющихся задач используйте планировщик wp-cron.
От функций к классу: как организовать растущий плагин
Пока в плагине пять строк, функции с префиксом — нормальный вариант. Когда их десятки, на помощь приходит класс: он собирает связанные функции вместе и сам подписывает их на хуки в конструкторе.
class MyFP_Plugin {
public function __construct() {
add_action('init', array($this, 'register_shortcodes'));
add_filter('the_content', array($this, 'append_note'));
}
public function register_shortcodes() {
add_shortcode('myfp_greeting', array($this, 'render_greeting'));
}
public function append_note($content) {
if (is_singular('post')) {
$content .= '<p class="myfp-note">Материал проверен редакцией.</p>';
}
return $content;
}
public function render_greeting() {
return '<p>Привет от My First Plugin!</p>';
}
}
new MyFP_Plugin(); Обратите внимание на запись array($this, ‘method’): так WordPress понимает, что обработчиком должен стать метод объекта, а не отдельная функция. Главный файл при этом остаётся тонким — он только подключает файлы из includes через require_once и запускает класс. Современная альтернатива ручным подключениям — автозагрузка по стандарту PSR-4, но для первого плагина достаточно и списка require_once.
Если класс добавляет шорткод, как в примере, параметры и вывод подробно разобраны в гайде про создание своих шорткодов в WordPress. А стили и скрипты для интерфейса подключайте только штатно — через wp_enqueue_scripts и правильное подключение CSS и JS.
Страница настроек в админке: меню и Settings API
Хорошему плагину нужен интерфейс: место, где владелец сайта включает опции, не заглядывая в код. Страницы в админке добавляет хук admin_menu, а хранение и проверку значений берёт на себя Settings API — встроенный механизм, который сам обрабатывает сохранение формы и защищает её от подделки.
add_action('admin_menu', function () {
add_options_page(
'My First Plugin',
'My First Plugin',
'manage_options',
'myfp-settings',
'myfp_render_settings_page'
);
});
add_action('admin_init', function () {
register_setting('myfp_settings', 'myfp_welcome_text', array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
));
}); Если плагин собран в класс, последним аргументом вместо имени функции передаётся массив с методом — array($this, ‘метод’). Функция вывода рисует обычную админскую форму: три вызова — settings_fields, do_settings_sections и submit_button — делают её полностью рабочей, сохранение и проверка уже внутри.
function myfp_render_settings_page() {
?>
<div class="wrap">
<h1>Настройки My First Plugin</h1>
<form method="post" action="options.php">
<?php
settings_fields('myfp_settings');
do_settings_sections('myfp_settings');
submit_button();
?>
</form>
</div>
<?php
} Если настроек много, одной страницей не обойтись: add_menu_page создаёт верхний уровень меню, add_submenu_page — вложенные разделы. Для интерфейсов, которые сохраняются без перезагрузки страницы, пригодится техника из статьи про AJAX в WordPress и admin-ajax.
Безопасность плагина: четыре привычки, которые спасают
Плагин работает с пользовательскими данными, поэтому первое правило — никому не доверять на входе. Большинство проблем закрывают четыре привычки: проверка прав, nonce, очистка данных и экранирование вывода.
Права доступа. Любое действие в админке проверяйте через current_user_can: сохранять настройки может только роль с правом manage_options, редактировать записи — те, кому это разрешено. Подробнее о ролях — в статье про пользовательские роли и права доступа.
Nonce. Скрытое одноразовое число защищает формы от подделки запроса: wp_nonce_field добавляет его в разметку, wp_verify_nonce проверяет при обработке. У форм Settings API эта защита встроена, для собственных обработчиков nonce добавляют вручную.
Очистка входных данных. Всё, что пришло из $_POST, $_GET или $_REQUEST, пропускают через санитайзеры: sanitize_text_field для строк, absint для чисел, esc_url_raw для адресов.
Экранирование вывода. Перед печатью данных в HTML их прогоняют через esc_html, esc_attr или esc_url — тогда даже вредоносная строка из базы останется текстом и не выполнится как разметка.
if (!isset($_POST['myfp_nonce']) || !wp_verify_nonce($_POST['myfp_nonce'], 'myfp_save')) {
wp_die('Проверка безопасности не пройдена.');
}
if (!current_user_can('manage_options')) {
wp_die('Недостаточно прав.');
}
$value = sanitize_text_field(wp_unslash($_POST['myfp_value']));
update_option('myfp_welcome_text', $value); Отдельная зона — запросы к базе: значения подставляйте в SQL только через метод prepare у объекта $wpdb, который экранирует параметры автоматически. Общие приёмы защиты сайта собраны в статье про безопасность WordPress для новичков.
Проверка и отладка: как убедиться, что плагин готов
Перед установкой на боевой сайт плагин стоит прогнать через простой чек-лист. Сначала включите отладку: константы в wp-config.php покажут замечания PHP и предупреждения WordPress, которые в обычном режиме скрыты.
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false); С такой настройкой ошибки записываются в файл wp-content/debug.log, а не ломают вёрстку у посетителей. Как читать этот файл и находить виновника — по шагам в статье про WP_DEBUG и отладку WordPress.
Второй помощник — плагин Query Monitor: он показывает, сколько запросов к базе делает ваш код, какие хуки сработали и откуда пришла ошибка. Третий — официальный Plugin Check, который проверяет плагин по требованиям каталога WordPress.org: безопасность, экранирование, текстовые домены.
wp plugin install plugin-check --activate
wp plugin check my-first-plugin Пройдитесь по чек-листу перед включением на рабочем сайте:
- в debug.log нет предупреждений, связанных с плагином;
- все входные данные очищаются, весь вывод экранируется;
- у функций и классов — уникальные префиксы, конфликтов нет;
- Plugin Check не выдаёт критичных замечаний;
- есть свежий бэкап и копия сайта для экспериментов.
Проверять плагин лучше на копии сайта, а перед любыми экспериментами делать свежий бэкап: как наладить резервное копирование WordPress, мы уже рассказывали.

Частые вопросы о создании плагина WordPress
С чего начать создание плагина WordPress?
Создайте в wp-content/plugins папку и положите в неё PHP-файл с заголовком Plugin Name — этого достаточно, чтобы плагин появился в админке. Затем добавьте проверку ABSPATH, определите префикс для функций и подпишите первую функцию на хук. Минимальный плагин — один файл; по мере роста его дополняют папками includes, admin и assets.
Чем плагин лучше кода в functions.php?
Код в плагине не привязан к теме: смена шаблона его не затронет, плагин включается и выключается из админки и переносится на другой сайт. Функциональность — типы записей, шорткоды, интеграции — принято выносить в плагин, а в functions.php дочерней темы оставлять только оформление.
Какие хуки нужно знать, чтобы написать плагин?
Для старта достаточно набора: init — регистрация возможностей, admin_menu — страницы в админке, admin_enqueue_scripts — ресурсы админки, the_content — правка вывода, wp_enqueue_scripts — ресурсы сайта, плюс хуки активации и деактивации. Остальные находятся по мере задач: ищите do_action и apply_filters в коде ядра и документации.
Что должно происходить при активации плагина?
Всё, что нужно сделать один раз: задать опции по умолчанию, при необходимости создать таблицы или роли, сохранить версию, сбросить правила ссылок через flush_rewrite_rules. Тяжёлые операции не должны выполняться на каждом запросе — для повторяющихся задач есть планировщик wp-cron.
Почему у функций плагина должен быть префикс?
PHP собирает все функции сайта в одно пространство имён, и короткое имя вроде get_data() почти наверняка столкнётся с темой или другим плагином — сайт упадёт с фатальной ошибкой. Уникальный префикс (например, myfp_) или классы решают проблему: риск конфликтов при обновлениях чужих расширений становится минимальным.
Как защитить формы и данные в плагине?
Проверяйте права через current_user_can, добавляйте в формы nonce и проверяйте его при обработке, очищайте входные данные санитайзерами (sanitize_text_field, absint) и экранируйте вывод (esc_html, esc_attr, esc_url). Для запросов к базе используйте метод prepare у объекта $wpdb — он экранирует подстановки автоматически.
Вывод
Свой плагин WordPress начинается с папки в wp-content/plugins и файла с заголовком Plugin Name — дальше добавляются структура, хуки, функции активации и деактивации, класс для порядка и страница настроек для удобства. Безопасность и отладка — не финальный штрих, а часть работы: nonce, очистка данных, экранирование и Plugin Check сопровождают плагин с первой версии.
Начните с маленького плагина под собственную задачу: пометка в записях, свой шорткод, простая настройка. Прогоните его через отладку, проверьте на копии сайта и только потом ставьте на рабочий проект. Так вы освоите механику WordPress без риска для боевого сайта.
А если нужен готовый плагин или доработка под задачи бизнеса — это к нам. Мы разрабатываем сайты и расширения на WordPress, интегрируем их с внешними сервисами и поддерживаем уже работающие проекты. Посмотрите услуги по разработке сайтов на WordPress, примеры выполненных проектов собраны в портфолио работ, а полезные материалы — в блоге о разработке сайтов. Нужна доработка существующего сайта? Можно заказать доработку сайта у программиста или описать задачу через форму обратной связи.



