Розробка кастомного плагіна MODX
Плагін MODX — код PHP, прив'язаний до системних подій. Перехоплює моменти життєвого циклу CMS: завантаження сторінки, збереження ресурсу, аутентифікація, помилки, кеш. На відміну від сніпета, плагін не повертає контент — він змінює поведінку системи.
Прив'язка до подій
// Плагін AutoSEO — автоматично заповнює SEO-поля
// Події: OnBeforeDocFormSave (перед збереженням ресурсу в менеджері)
$eventName = $modx->event->name;
switch ($eventName) {
case 'OnBeforeDocFormSave':
handleBeforeSave($modx, $resource, $mode);
break;
case 'OnDocFormSave':
handleAfterSave($modx, $resource, $mode);
break;
}
function handleBeforeSave($modx, $resource, $mode): void {
// Автозаповнення description з introtext
if (empty($resource->get('description')) && !empty($resource->get('introtext'))) {
$description = mb_substr(strip_tags($resource->get('introtext')), 0, 160);
$resource->set('description', $description);
}
// Автозаповнення longtitle з pagetitle
if (empty($resource->get('longtitle'))) {
$resource->set('longtitle', $resource->get('pagetitle'));
}
}
Популярні події MODX
| Подія | Коли | Застосування |
|---|---|---|
| OnPageNotFound | Помилка 404 | Кастомна 404, редиректи |
| OnHandleRequest | Кожний запит | Редиректи, геолокація |
| OnLoadWebDocument | Завантаження ресурсу | Модифікація контенту |
| OnBeforeDocFormSave | Перед збереженням в менеджері | Валідація, автозаповнення |
| OnDocFormSave | Після збереження | Синхронізація з зовнішньою системою |
| OnUserLogin | Вхід користувача | Логування, 2FA |
| OnCacheUpdate | Очищення кешу | Синхронізація CDN |
| OnSiteRefresh | Скидання налаштувань | Гаки развертання |
Плагін 301-редиректів
<?php
// Плагін Redirects
// Подія: OnPageNotFound
$uri = $_SERVER['REQUEST_URI'];
$redirects = $modx->getOption('custom_redirects', null, '');
// Редиректи зберігаються як JSON у системному налаштуванні
$redirectMap = json_decode($redirects, true) ?? [];
foreach ($redirectMap as $from => $to) {
if (strpos($uri, $from) === 0) {
$target = str_replace($from, $to, $uri);
$modx->sendRedirect($target, ['responseCode' => 'HTTP/1.1 301 Moved Permanently']);
exit;
}
}
// Показати кастомну сторінку 404
$errorPage = $modx->getOption('error_page', null, 404);
$modx->sendForward($errorPage, ['response_code' => 'HTTP/1.1 404 Not Found']);
Плагін геолокації
<?php
// Плагін GeoRedirect
// Подія: OnHandleRequest
if ($modx->context->key === 'web') {
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? '';
// Тільки при першому відвідуванні (без кукі)
if (!isset($_COOKIE['geo_redirect_done'])) {
$geoData = getGeoByIp($ip);
$currentUri = $_SERVER['REQUEST_URI'];
$countryContextMap = ['BY' => 'by', 'UA' => 'ua', 'KZ' => 'kz'];
$targetContext = $countryContextMap[$geoData['country']] ?? null;
if ($targetContext && $modx->context->key !== $targetContext) {
setcookie('geo_redirect_done', '1', time() + 86400, '/');
$modx->sendRedirect('/' . $targetContext . $currentUri);
exit;
}
}
}
function getGeoByIp(string $ip): array {
// MaxMind GeoIP2 або ipapi.co
$response = file_get_contents("https://ipapi.co/{$ip}/json/");
return json_decode($response, true) ?? ['country' => 'RU'];
}
Плагін синхронізації з CRM
<?php
// Плагін CRMSync
// Подія: OnDocFormSave
if ($modx->event->params['mode'] === modSystemEvent::MODE_UPD
&& in_array($resource->get('template'), [5, 6])) { // тільки визначені шаблони
$crmApiKey = $modx->getOption('crm_api_key');
$crmApiUrl = $modx->getOption('crm_api_url');
$data = [
'id' => $resource->id,
'title' => $resource->get('pagetitle'),
'url' => $modx->makeUrl($resource->id, '', '', 'full'),
'price' => $resource->getTVValue('price'),
'category' => $resource->get('parent'),
'updated' => time(),
];
$ch = curl_init($crmApiUrl . '/products/' . $resource->id);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $crmApiKey,
],
CURLOPT_TIMEOUT => 5,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 400) {
$modx->log(modX::LOG_LEVEL_ERROR, "CRM sync failed for resource {$resource->id}: {$response}");
}
}
Зберігання плагіна у файлі
// У редакторі плагіна: File Source = файлова система
// Файл: core/components/myplugin/myplugin.plugin.php
// Це дозволяє версіонувати плагін у git
Плагін StaticElements синхронізує плагіни між БД та файловою системою.
Терміни
Розробка плагіна для однієї-двох подій — 0,5–1 день. Складний плагін з кількома подіями та зовнішніми інтеграціями — 2–4 дні.







