Николай Ланец
12 июня 2013 г., 1:32

Обновление MODX Revolution 2.0.8 до версии 2.2.5

Сегодня проводил обновление сайта на MODX Revolution 2.0.8 до версии 2.2.5 и хочу поделиться опытом, может кому пригодится.
Для начала проблема: нельзя 2.0.8 обновить сразу до версии 2.2.5 в автоматическом режиме (если у кого-то есть другое мнение, с радостью выслушаю). Со времен 2.0.х не только удалили много деприкативного кода, так еще и добавили много всего, и изменения коснулись не только файловой системы, но и в базе данных много изменений появилось. В связи с этим увидел только один вариант: развернуть новый сайт и перенести туда все из старого. И как оказалось, это не так уж и сложно оказалось сделать. Здесь вам phpMyAdmin в помощь. Но успех переноса обратнопропорционален привычке вносить изменения в сторонние пакеты (в том числе и в базовые настройки пакетов).
Итак, постараюсь вкратце описать принцип. Последовательность действий такая: 1. Обязательно делаем резервные копии сайта и базы данных. 2. Создаем новый сайт и инсталлируем последнюю версию MODX Revolution (кстати, при переносе я очень оценил тот факт, что Рева ставится голая, без всяких чанков, сниппетов и т.п., так как нам предстоит перенести все свое, и нам вообще не нужны конфликты в базе данных). 3. В базе данных нового сайта удаляем базовый шаблон из таблицы site_templates. Все, заготовка у нас есть. Дальше нам надо перенести все с прошлого сайта. 4. Копируем все содержимое папок /assets/, /core/components/ (и своих папок, если вы любите выходить за рамки системы). 5. Вручную копируем все содержимое таблиц с шаблонами, чанками, сниппетами, тв-параметрами, группами пользователей и т.д. (кроме таблиц системных событий, шаблонов политик безопасности и т.п., если вы туда ничего не дополняли). Это самый сложный пункт, требующий навыков работы с БД, и знание структуры БД MODX. Его опишу подробней дальше. 6. Инсталлируем последние версии используемых ранее пакетов. 7. Копируем содержимое таблиц инсталлируемых пакетов. К примеру у меня был установлен Gallery, у него есть свои таблицы. Но в принципе я его таблицы сразу перенес, еще до установки пакета, и проблем не возникло, так как при установке пакета имеющиеся таблицы не затирались. 8. Может понадобиться обновление документов, если у вас ЧПУ и простое обновление кеша сайта не помогло. Но если такое и случится, напишите циркулярную функцию, которая пройдется по всем документам и с полученными объектами выполнит save(); Если уж вообще не захочется заморачиваться, то можно вот такой простой код выполнить:
$docs = $modx->getCollection('modResource'); foreach($docs as &$doc){ $doc->save(); }
Вот вроде бы и все. Конечно надо брать во внимание, что могут быть использованы сторонние пакеты, не совместимые с последней версией Ревы, и т.п., но это может показать только вскрытие. Мой сайт двухгодичной давности переехал без особых проблем. Главное не перепутать местами пункты 5 и 6.
Итак, по переносу содержимого таблиц из прошло базы. Здесь главное написать запросы с нужным количеством колонок, так как многие таблицы будут отличаться (в новых таблицах появились новые колонки, а какие-то удалили (как колонки haskeywords, hasmetatags в таблице site_content и т.п.)). Здесь можно использовать вот такую последовательность: 1. Открываем целевую таблицу в новой базе данных в phpMyAdmin (или кто что использует, но способ описываю для pma). 2. Нажимаем ссылку insert (чтобы вставить новую запись), и не заполняя поля, жмем GO. pma вставит пустую запись и покажет выполненные запрос со всеми колонками. (показываю на заполненной таблице, потому у меня не ноль записей. У вас таблица должна быть пустая в новой базе.). Все, мы получили список всех колонок в новой таблице. 3. Удаляем новую запись, она нам вообще не нужна. 4. Теперь сформируем заготовку на копирование данных. Общая структура запроса будет такая: insert into table (COLUMNS) select COLUMNS from old_db.table; Число вставляемых колонок, и извлекаемых из старой таблицы колонок должно совпадать. Так же и извлекаемые колонки, и вставляемые должны присутствовать в обеих таблицах. Колонок может быть меньше, чем в целевой таблице, но не больше. Итак, дальнейшими манипуляциями мы получим запрос с максимальным числом колонок из старой таблицы, которые есть в новой таблице. Вот у нас запрос, который мы получили при вставке пустой строки:
INSERT INTO `modx_site_content` ( `id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `content`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type`, `uri`, `uri_override`, `hide_children_in_tree`, `show_in_tree`, `properties` ) VALUES ( NULL, 'document', 'text/html', '', '', '', '', '', '0', '0', '0', '0', '0', NULL, NULL, '1', '0', '0', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '', '0', '0', '0', '0', '0', 'modDocument', 'web', '1', NULL, '0', '0', '1', NULL );

Здесь у нас уже перечислены все колонки из новой таблицы. Копируем названия этих колонок и формируем такой запрос:
INSERT INTO `modx_site_content` SELECT `id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `content`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type`, `uri`, `uri_override`, `hide_children_in_tree`, `show_in_tree`, `properties` FROM old_db.modx_site_content

Если сейчас выполнить этот запрос на целевой базе, то мы получим ошибку Unknown column 'uri' in 'field list'. Эта ошибка говорит о том, что в таблице, из которой мы пытаемся извлечь записи, нет колонци uri (ее ведь действительно не было в версии 2.0.8). Хорошо, удаляем эту колонку из списка в запросе и опять выполняем запрос. Следующая ошибка: Unknown column 'uri_override' in 'field list'. Делаем то же самое, и так пока не уберем из списка все колонки, которых нет в старой таблице. Так мы будем делать, пока не получим новое сообщение: Column count doesn't match value count at row 1. Это сообщение говорит о том, что количество колонок в целевой таблице и в извлекаемой, не совпадает (именно в рамках запроса). Сейчас получается то, что запрос из старой таблицы выполняется нормально, но данные в таблицу не могут попасть, так как количество колонок не совпадает, а явно колонки мы не объявили. Для этого мы просто копируем извлекаемые колонки и вставляем их в скобочки за названием целевой таблицы. Запрос получается такой:
INSERT INTO `modx_site_content` ( `id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `content`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type` ) SELECT `id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `content`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type` FROM old_db.modx_site_content

Все, выполняем этот запрос и все должно быть ОК.
Таким образом придется сделать на всех целевых таблицах. Кстати, вот такая хитрость еще есть, чтобы перенести свои данные в таблицы, в которых есть уже данные (Например, перенести свои шаблоны политик безопасности). Для этого надо сформировать такой запрос: insert ignore into table (coluns) select (columns) from old_db.table; При таком запросе ошибки, возникающие при конфликтах первичных ключей, не будут прекращать весь процесс копирования, а будут игнорироваться, в результате чего будут вставлены только уникальные записи. Но важно понимать, что для этого должны быть настроены первичные (или хотя бы просто уникальные) ключи на целевых таблицах.
Попробую перечислить все целевые таблицы (если у вас в старой базе на каких-то таблицах нет записей, само собой их пропускаем):
  • access_resources
  • access_resource_groups
  • access_templatevars
  • categories
  • categories_closure
  • context (только если у вас больше контекстов, кроме web и mgr)
  • context_setting
  • lexicon_entries
  • membergroup_names
  • member_groups (эти две таблицы только если дополнительно настраивали политики безопасности)
  • namespaces (проверьте данные записи на предмет абсолютных путей, и если что, поправьте пути с использованием MODX-переменных {core_path} и т.п.)
  • property_set
  • site_content
  • site_htmlsnippets
  • site_plugins
  • site_plugin_events
  • site_snippets
  • site_templates
  • site_tmplvars
  • site_tmplvar_access
  • site_tmplvar_contentvalues
  • site_tmplvar_templates
  • system_settings (только обновление записей и очень аккуратно. Если в старом сайте особо ничего не настраивали, лучше этого вообще не делать и возможные настройки выполнить вручную).
  • users
  • user_attributes
  • user_group_roles (тоже только в случае если проводились настройки политик безопасности)
  • user_settings
  • workspaces (тоже проверить пути)
Вот вроде бы и все.

Добавить комментарий