Міграція сайту з MODX Evolution на MODX Revolution
MODX Evolution та Revolution — принципово різні системи. Evolution: PHP-процедурний підхід, немає OOP, немає namespace, API через глобальні об'єкти $modx. Revolution: PSR-сумісна архітектура, xPDO ORM, компоненти (Extras). Прямого upgrade-шляху немає — потрібна повноцінна міграція контенту.
Аналіз поточного Evolution сайту
-- Кількість документів за шаблонами
SELECT t.templatename, COUNT(d.id) as count
FROM site_content d
JOIN site_templates t ON t.id = d.template
GROUP BY t.templatename;
-- TV-параметри
SELECT tv.caption, tv.type, COUNT(tvv.id) as used
FROM site_tmplvars tv
LEFT JOIN site_tmplvar_contentvalues tvv ON tv.id = tvv.tmplvarid
GROUP BY tv.id;
-- Кастомні сніпети
SELECT name, LENGTH(snippet) as size FROM site_snippets;
-- Плагіни
SELECT name, plugincode FROM site_plugins WHERE disabled = 0;
Експорт контенту з Evolution
// Скрипт експорту в JSON (запустити на Evolution-сервері)
$db = new PDO('mysql:host=localhost;dbname=modx_evo;charset=utf8', 'user', 'pass');
$resources = $db->query("
SELECT d.*, t.templatename
FROM site_content d
JOIN site_templates t ON t.id = d.template
WHERE d.deleted = 0
ORDER BY d.parent, d.menuindex
")->fetchAll(PDO::FETCH_ASSOC);
foreach ($resources as &$resource) {
// Отримати TV-значення
$tvs = $db->prepare("
SELECT tv.name, tvv.value
FROM site_tmplvar_contentvalues tvv
JOIN site_tmplvars tv ON tv.id = tvv.tmplvarid
WHERE tvv.contentid = ?
");
$tvs->execute([$resource['id']]);
$resource['tvs'] = $tvs->fetchAll(PDO::FETCH_KEY_PAIR);
}
file_put_contents('content-export.json', json_encode($resources, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
Імпорт у MODX Revolution
// Скрипт імпорту (запустити на Revolution-сервері після установки)
require_once 'config.core.php';
require_once MODX_CORE_PATH . 'model/modx/modx.class.php';
$modx = new modX();
$modx->initialize('web');
$data = json_decode(file_get_contents('content-export.json'), true);
// Маппінг старих шаблонів на нові
$templateMap = [
'default_template' => 1,
'inner_page' => 2,
'catalog' => 3,
'product' => 4,
];
// Маппінг старих parent ID на нові (після зміни структури)
$parentMap = [];
foreach ($data as $evo_resource) {
$resource = $modx->newObject('modDocument');
$resource->fromArray([
'pagetitle' => $evo_resource['pagetitle'],
'longtitle' => $evo_resource['longtitle'],
'description' => $evo_resource['description'],
'alias' => $evo_resource['alias'],
'introtext' => $evo_resource['introtext'],
'content' => migrateContent($evo_resource['content']),
'published' => $evo_resource['published'],
'publishedon' => $evo_resource['publishedon'],
'createdon' => $evo_resource['createdon'],
'template' => $templateMap[$evo_resource['templatename']] ?? 1,
'parent' => $parentMap[$evo_resource['parent']] ?? 0,
'menuindex' => $evo_resource['menuindex'],
]);
if ($resource->save()) {
$parentMap[$evo_resource['id']] = $resource->id;
// Мігрувати TV
foreach ($evo_resource['tvs'] as $tvName => $tvValue) {
$resource->setTVValue($tvName, $tvValue);
}
}
}
// Функція міграції контенту (теги Evolution → Revolution)
function migrateContent(string $content): string {
// Evolution використовує [*alias*] для посилань, Revolution — [[~id]]
// Заміна потребує ручного маппінгу або алісів
// Убрати застарілі Evolution-теги
$content = preg_replace('/\[(\*|\+|\!)[^\]]+\]/', '', $content);
return $content;
}
Міграція сніпетів та плагінів
Сніпети Evolution написані в процедурному стилі з глобальним $modx. В Revolution API інший:
// Evolution (старий API)
$docs = $modx->getDocuments($parents = [5], $published = 1);
// Revolution (правильний API)
$c = $modx->newQuery('modResource');
$c->where(['parent' => 5, 'published' => 1]);
$docs = $modx->getCollection('modResource', $c);
Сніпети потрібно переписувати. Для типових завдань (вивід списків, меню, форм) — використовувати готові Revolution Extra: pdoResources, pdoMenu, FormIt.
Міграція зображень
# Структура зображень папки однакова (assets/images/)
rsync -avz old-server:/var/www/evo-site/assets/images/ \
/var/www/revo-site/assets/images/
Шляхи в HTML-контенті можуть потребувати заміни якщо змінилася структура директорій.
Строк виконання
| Тип сайту | Строк |
|---|---|
| Простий сайт (до 50 ресурсів, стандартні сніпети) | 1–2 тижні |
| Середній (100–500 ресурсів, кастомні сніпети) | 3–5 тижнів |
| Крупний (1000+ ресурсів, складний функціонал) | 2–3 місяця |







