Модульная система — главное преимущество современной CMS. Она позволяет расширять функциональность без правки ядра. Разберу, как написать свой модуль за час — на примере простого модуля «Счётчик посещений».
Как устроена модульная система
В основе — три механизма:
- Хуки (actions) — точки, куда можно «прицепить» свой код
- Фильтры (filters) — модификация значений на лету
- Автозагрузка — CMS сама подключает активные модули
Это та же идея, что в WordPress, но проще реализована.
Структура модуля
/modules/my-module/
├── module.json ← метаданные
├── module.php ← логика (главный файл)
├── admin.php ← страница настроек (опционально)
└── assets/
├── css/style.css
└── js/script.js
Шаг 1. Файл module.json
{
"slug": "my-module",
"name": "My Module",
"version": "1.0.0",
"author": "Ваше имя",
"description": "Что делает модуль"
}
Без этого файла CMS не увидит модуль.
Шаг 2. Основной файл module.php
Задача: считать посетителей и записывать в БД.
<?php
// Регистрируем хук на каждую загрузку страницы
add_action('site.body.start', function() {
global $pdo;
// Уникальный ID посетителя (сессия)
if (empty($_SESSION['visitor_id'])) {
$_SESSION['visitor_id'] = bin2hex(random_bytes(8));
}
$vid = $_SESSION['visitor_id'];
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
$url = $_SERVER['REQUEST_URI'] ?? '/';
// Пишем в БД (не чаще раза в 10 минут)
$stmt = $pdo->prepare("
SELECT id FROM visits
WHERE visitor_id = ? AND created_at > NOW() - INTERVAL 10 MINUTE
LIMIT 1
");
$stmt->execute([$vid]);
if (!$stmt->fetch()) {
$pdo->prepare("INSERT INTO visits (visitor_id, ip, url) VALUES (?, ?, ?)")
->execute([$vid, $ip, $url]);
}
});
Всё. Модуль уже работает — считает посещения.
Шаг 3. Своя таблица в БД
Модуль должен сам создавать свою таблицу при активации. Для этого используется admin.php:
<?php
// Проверяем и создаём таблицу
global $pdo;
$pdo->exec("
CREATE TABLE IF NOT EXISTS visits (
id INT AUTO_INCREMENT PRIMARY KEY,
visitor_id VARCHAR(32) NOT NULL,
ip VARCHAR(45) DEFAULT '',
url VARCHAR(500) DEFAULT '',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
KEY idx_visitor (visitor_id),
KEY idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
");
// Выводим статистику
$total = $pdo->query("SELECT COUNT(*) FROM visits")->fetchColumn();
$today = $pdo->query("SELECT COUNT(DISTINCT visitor_id) FROM visits WHERE DATE(created_at) = CURDATE()")->fetchColumn();
?>
<h2>Статистика посещений</h2>
<p>Всего визитов: <?= $total ?></p>
<p>Сегодня: <?= $today ?></p>
Шаг 4. Доступные хуки
| Хук | Где срабатывает |
|---|---|
site.head | Внутри <head> публички |
site.body.start | Сразу после <body> |
site.footer | Перед </body> |
admin.head | Внутри <head> админки |
admin.footer | Перед </body> админки |
Шаг 5. Фильтры (модификация значений)
Пример: добавить к каждому заголовку страницы название сайта.
add_filter('page.title', function($title) {
return $title . ' — Мой сайт';
});
Фильтр принимает значение и возвращает новое. Не echo, не записывает — возвращает.
Шаг 6. Установка модуля
- Упаковать папку
my-moduleв ZIP - Открыть админку → Система → Модули
- Загрузить ZIP
- CMS проверит безопасность (нет ли опасных функций в коде)
- Активировать
Что важно знать
- CSP запрещает inline onclick в админке. Используй
data-action+addEventListenerили внешний JS. - Не пиши в ядро — модуль не должен править файлы движка.
- Свои таблицы — префикс модуля, чтобы не пересекаться с другими (например,
mymodule_visits). - Настройки — в таблицу modules.settings (JSON).
Что можно сделать модулем
- Интеграция с Telegram-ботом
- Онлайн-оплата через ЮKassa
- Промокоды и скидки
- Свои формы (обратная связь, заявки)
- SMS-уведомления
- Мультиязычность
- Экспорт данных в Excel
Модульная система — то, что отличает «просто сайт» от «платформы для сайтов». Если CMS без модулей — она рано или поздно упрётся в потолок. Если с модулями — растёт вместе с проектом.
Kuznya CMS — движок с модульной системой на хуках и фильтрах. Можно расширять без правки ядра.