Коротка відповідь

  1. Дізнайтесь версію OpenCart (вона внизу адмінки) і звірте з PHP нового сервера: у Hosturm це PHP 8.3, гілка 2.x на ньому не запуститься.
  2. Скопіюйте весь корінь магазину і окремо теку storage, якщо вона винесена за межі public_html.
  3. Вивантажте базу, розгорніть її на новому сервері і перепишіть обидва конфіги: config.php і admin/config.php.
  4. Оновіть кеш модифікацій, перевірте кошик і тестове замовлення через файл hosts.
  5. Увімкніть режим обслуговування, зробіть фінальний дамп бази, перемкніть A-записи - і лише тоді перевіряйте онлайн-оплату.

Магазин відрізняється від блогу одним: у ньому щохвилини з'являються дані, які не можна загубити, - замовлення, реєстрації, залишки. Тому найважливіший крок тут не копіювання, а момент заморозки перед фінальним дампом.

Що саме переїжджає в OpenCart

OpenCart тримає абсолютні шляхи до своїх тек прямо в конфігах. Саме через це «скопіював файли - і все працює» з ним не буває: на новому сервері інший користувач і інша структура каталогів, а магазин продовжує шукати себе за старою адресою на диску.

ЩоДе лежитьЩо з ним зробити
Ядро, тема, модуліpublic_html: admin, catalog, systemскопіювати повністю
Фото товарівimage/catalogскопіювати; image/cache можна не брати
Тека storagesystem/storage або поруч із public_htmlскопіювати без cache і logs
Конфігиconfig.php і admin/config.phpпереписати шляхи і дані бази
БазаMySQL, таблиці з префіксом oc_дамп і імпорт, двічі: тестовий і фінальний
ЧПУ-адреси.htaccess у кореніперевірити, що файл переїхав
Cronу панелі старого хостингувідтворити в DirectAdmin

Крок 0. Перед переносом: версія, модулі, тариф

Версію OpenCart видно в нижньому рядку адмінки. Третя гілка від 3.0.3 і вся четверта запускаються на PHP 8.3 - саме ця версія зараз на сервері Hosturm. Гілка 2.x на ньому не стартує, а старішого PHP на сервері немає - такий магазин спершу оновлюють, а вже потім везуть. Детальна таблиця сумісності є в статті «Хостинг для OpenCart і PrestaShop».

Далі випишіть модулі оплати, доставки та обміну з 1С або CRM. Зверніть увагу на закодовані ionCube: ionCube Loader на сервері є, але частина таких модулів прив'язує ліцензію до домену, а деякі - до IP сервера. Якщо домен лишається той самий, зазвичай нічого не треба; прив'язку до IP доведеться перевипускати у розробника модуля, і краще спитати його про це до переїзду, а не в неділю ввечері.

Тариф під магазин (ціна за річної оплати, ресурси - з таблиці порівняння на головній):

ТарифЦінаCPU / RAM / NVMeСайтів / базДля якого магазину
Старт142 грн/міс1 ядро / 2 GB / 10 GB1 / 5один магазин до кількох сотень товарів
Оптимал229 грн/міс2 ядра / 3 GB / 20 GB3 / 10магазин і тестова копія на піддомені
Бізнес350 грн/міс3 ядра / 4 GB / 30 GB5 / 20тисячі товарів, платна реклама
Pro800 грн/міс4 ядра / 8 GB / 100 GB10 / без обмеженькілька магазинів, великий фотокаталог

Якщо платити помісячно, Старт коштує 479 грн, Оптимал - 599, Бізнес - 759, Pro - 1 119 грн/міс. Повне порівняння - на сторінці хостингу. Щоб не вгадувати з місцем, подивіться на старому хостингу розмір теки image: у магазинів саме вона займає 80-90% обсягу, а не код.

За добу до переносу знизьте TTL записів домену до 300 секунд - навіщо це і де його шукати у реєстратора, розписано в статті про A-запис і NS.

Крок 1. Скопіювати файли разом зі storage

Відкрийте config.php у корені старого магазину і знайдіть рядок DIR_STORAGE. Якщо там .../system/storage/, тека лежить усередині сайту і скопіюється разом з усім. Якщо шлях веде за межі public_html (установник OpenCart 3 пропонує таке перенесення з міркувань безпеки), цю теку треба забрати окремо - її часто забувають, а в ній живуть завантажені покупцями файли, сесії і згенеровані модифікації.

Через файловий менеджер

Запакуйте корінь магазину в один архів у панелі старого хостингу. Перед архівацією видаліть вміст image/cache, system/storage/cache і system/storage/logs: мініатюри OpenCart згенерує сам при першому перегляді, а логи помилок на великих магазинах важать гігабайти. Архів стане в кілька разів меншим.

Через FTP

Якщо архів створити не можна, качайте клієнтом на кшталт FileZilla з увімкненим показом прихованих файлів - інакше загубиться .htaccess. Для каталогу з десятками тисяч фото FTP працює годинами, тому архів майже завжди вигідніший. Налаштування клієнта і різницю у швидкості я показував у матеріалі FTP чи файловий менеджер.

Крок 2. База даних: дамп і одна пастка з кодуванням

Ім'я бази, користувача і префікс таблиць беріть з того ж config.php: рядки DB_DATABASE, DB_USERNAME і DB_PREFIX. У phpMyAdmin старого хостингу оберіть цю базу, Експорт, формат SQL, стиснення gzip. Таблицю oc_session можна перед цим очистити: в ній лише сесії відвідувачів, а на магазинах з трафіком вона займає сотні мегабайтів.

На новому сервері створіть базу і користувача - покроково з назвами розділів панелі це описано в статті як створити базу даних у DirectAdmin. Далі phpMyAdmin, Імпорт, файл .sql.gz.

Пастка, на яку я натрапляю найчастіше: якщо старий хостинг працював на MySQL 8, дамп містить кодування utf8mb4_0900_ai_ci. На сервері стоїть MariaDB 10.11, і вона такого порівняння не знає - імпорт падає з помилкою Unknown collation. Розпакуйте дамп, замініть у текстовому редакторі всі utf8mb4_0900_ai_ci на utf8mb4_unicode_ci і імпортуйте ще раз. Для бази на кілька гігабайтів через браузер цього не зробити - надішліть дамп мені в Telegram, виправлю і заллю з консолі.

Крок 3. Переписати два config.php

Це серце переносу OpenCart. Конфігів два, і правити треба обидва однаково - магазин з виправленим лише одним файлом відкривається, а адмінка ні (або навпаки). У DirectAdmin корінь сайту має вигляд /home/користувач/domains/example.com/public_html/, де «користувач» - логін акаунта з листа.

КонстантаЩо в нійЩо вписати
DIR_APPLICATION, DIR_SYSTEM, DIR_IMAGEстарий шлях на дискуновий шлях до public_html
DIR_STORAGEшлях до storageнове розташування теки
HTTP_SERVER, HTTPS_SERVERадреса магазинуне чіпати, якщо домен той самий
DB_HOSTNAMEсервер базиlocalhost
DB_USERNAME, DB_PASSWORD, DB_DATABASEдоступ до базинові дані з панелі, з префіксом акаунта
DB_PREFIXпрефікс таблицьзалишити як був

Найпростіше знайти старий шлях один раз (наприклад, /home/u12345/public_html/) і замінити його в обох файлах пошуком із заміною. Після правки в кожному файлі не має лишитися жодного рядка зі старим шляхом - одна пропущена константа дає помилку на кшталт fopen(...): Failed to open stream лише на певних сторінках.

Крок 4. Кеш модифікацій, ЧПУ і ліміти PHP

Модифікації. В OpenCart 3 більшість модулів вбудовуються через OCMOD, і результат лежить у storage/modification вже зі старими шляхами. Зайдіть в адмінку: Розширення → Модифікації, праворуч угорі кнопка «Оновити». Потім на головній панелі адмінки натисніть шестерню і скиньте кеш тем і SASS. Без цього частина модулів мовчки не працює, хоча в списку позначена як увімкнена.

ЧПУ. OpenCart постачається з файлом .htaccess.txt, а працює лише .htaccess. Якщо на старому сервері адреси товарів були людськими, а на новому всі сторінки, крім головної, віддають 404 - файл не переїхав або лишився з розширенням .txt. Сам перемикач ЧПУ в Система → Налаштування → Сервер зберігається в базі, його чіпати не треба.

Ліміти. Заводський max_input_vars на 1000 обрізає товари з великою кількістю опцій. Створіть у корені .user.ini з рядками max_input_vars = 10000 і memory_limit = 256M. Директиви php_value у .htaccess зі старих інструкцій не переносіть: на сервері PHP-FPM, і вони дадуть помилку 500 на всьому магазині.

Крок 5. Перевірити магазин до перемикання домену

Пропишіть у файлі hosts свого комп'ютера IP нового сервера для домену і www-версії - механізм розібрано в статті як перенести сайт без простою. Для магазину перевірка ширша, ніж для сайту-візитки:

  • категорія з фільтром, картка товару з опціями, пошук;
  • реєстрація нового покупця і вхід у кабінет;
  • кошик і оформлення замовлення зі способом «оплата при отриманні»;
  • вхід в адмінку і збереження будь-якого товару без змін;
  • розрахунок доставки, якщо модуль тягне тарифи перевізника через API.

Онлайн-оплату на цьому етапі перевірити не вийде, і це нормально. Платіжний сервіс після оплати стукає на ваш домен, а для всього світу, крім вашого комп'ютера, домен ще вказує на старий сервер - підтвердження піде туди. Тестове замовлення з оплатою карткою робіть уже після перемикання DNS.

Крок 6. Заморозка, фінальний дамп і DNS

  1. Режим обслуговування. На старому сервері: Система → Налаштування → Сервер → Режим обслуговування. Покупці бачать заглушку, адміністратор, залогінений в адмінці, - робочий магазин. Для більшості українських магазинів найтихіше вікно - з 2 до 6 ранку.
  2. Фінальний дамп. Вивантажте базу вдруге, в новій базі видаліть усі таблиці і імпортуйте свіжий дамп. Так замовлення, зроблені після тестового дампу, не пропадуть. Якщо покупці завантажували файли до замовлень, заберіть і нові файли з storage/upload.
  3. DNS. Змініть A-записи @ і www на IP нового сервера. На новому сервері режим обслуговування вимкніть одразу - він приїхав разом із базою.
  4. SSL і оплата. Щойно домен почне відкриватися з нового сервера, випустіть сертифікат Let's Encrypt у DirectAdmin і зробіть одне реальне замовлення з оплатою карткою на мінімальну суму.

Старий акаунт не закривайте ще тиждень-два: частина покупців зі збереженим DNS-кешем може оформити замовлення там. Раз на день перевіряйте в старій адмінці, чи не з'явилось нових, і переносьте їх руками.

Якщо щось не працює

  • Біла сторінка або 500 - дивіться error_log у теці домену. Найчастіше це модуль, написаний під PHP 7, або php_value у .htaccess.
  • «Failed to open stream» зі старим шляхом - пропущена константа в одному з двох config.php або старі шляхи в кеші модифікацій. Оновіть модифікації ще раз.
  • Адмінка викидає на сторінку входу після кожного кліку - у admin/config.php домен у HTTP_SERVER не збігається з адресою, на якій ви заходите (з www і без www - це різні адреси для cookies).
  • Немає фото товарів - не скопіювалась image/catalog або права на image/cache не дозволяють запис. Потрібно 755 для тек.
  • Модуль пише «License invalid» - ionCube-ліцензія прив'язана до IP старого сервера, перевипуск робить автор модуля.
  • Замовлення з оплатою мають статус «Очікування» - платіжний сервіс не достукався до сайту. Перевірте в кабінеті сервісу адресу callback і що вона на https.

Якщо помилку не видно ні в логах, ні в цьому списку, надішліть у Telegram версію OpenCart і текст помилки - подивлюсь на сервері напряму.

Коротко

Перенести OpenCart на інший хостинг - це не про копіювання, а про три місця, де магазин пам'ятає старий сервер: два config.php, тека storage і кеш модифікацій. Поправте їх, перевірте замовлення через hosts, заморозьте магазин на час фінального дампу - і покупці переїзду не помітять. Якщо займатися цим самостійно немає часу, переношу магазини сам і безкоштовно, разом із перевіркою оплати після перемикання. Обрати тариф можна на сторінці хостингу, а для магазину з тестовою копією одразу замовити Оптимал за 229 грн/міс.