Миграция сайта с 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 месяца |







