Налаштування імпорту/експорту товарів OpenCart
Ручне заведення каталогу в OpenCart — це тупик при будь-якій кількості SKU свыше кілька сотень. Налаштування пайплайну імпорту/експорту вирішує три завдання одночасно: первинне наповнення каталогу, регулярне оновлення цін і остатків, синхронізація з зовнішніми системами (1C, МойСклад, ERP).
Вбудовані можливості OpenCart
Стандартний OpenCart містить базовий CSV-імпорт через admin > Catalog > Import. Формат жорсткий: фіксовані колонки без підтримки варіантів товару, атрибутів, SEO-полів і мультимовності. Підходить тільки для найпростіших випадків.
Таблиці, що змінюються при повному імпорту:
| Таблиця | Вміст |
|---|---|
oc_product |
Основні поля: ціна, вага, модель, статус |
oc_product_description |
Тексти по мовах |
oc_product_to_category |
Прив'язка до категорій |
oc_product_to_store |
Прив'язка до магазинів |
oc_product_attribute |
Значення атрибутів |
oc_product_option |
Опції (колір, розмір) |
oc_product_option_value |
Значення опцій з остатком |
oc_product_image |
Додаткові зображення |
oc_product_to_layout |
SEO layout |
Модулі для імпорту/експорту
Journal3 / QuickAdmin — вбудовані в деякі теми, достатні для простих каталогів.
Spreadsheet Price Manager (SPM) — працює з Google Sheets безпосередньо через API, зручно для команд без технічних навичок.
Import/Export Pro (iSenseLabs / Opencart.com) — найповніший офіційний варіант. Підтримує XML, CSV, XLS, JSON. Маппінг колонок через UI, розписання по cron, обробка зображень по URL.
D-Import — альтернатива з акцентом на продуктивність; використовує bulk INSERT з відключенням індексів під час завантаження.
Кастомний імпорт через скрипт
Для максимальної гнучкості — CLI-скрипт, що використовує OpenCart framework безпосередньо:
<?php
// tools/import_products.php
define('DIR_APPLICATION', __DIR__ . '/../admin/');
define('DIR_SYSTEM', __DIR__ . '/../system/');
// ... решта констант
require_once(DIR_SYSTEM . 'startup.php');
require_once(DIR_APPLICATION . 'config.php');
$registry = new Registry();
// ініціалізація DB, Config, Load...
$csv = new SplFileObject('/tmp/products_feed.csv');
$csv->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY);
$csv->setCsvControl(';', '"');
$headers = $csv->current(); // перша рядок — заголовки
$csv->next();
$db->query("SET foreign_key_checks = 0");
$db->query("SET unique_checks = 0");
while (!$csv->eof()) {
$row = array_combine($headers, $csv->current());
$csv->next();
if (empty($row['model'])) continue;
// Перевіряємо існування по model
$existing = $db->query(
"SELECT product_id FROM oc_product WHERE model = '" . $db->escape($row['model']) . "' LIMIT 1"
);
if ($existing->num_rows) {
$product_id = $existing->row['product_id'];
// UPDATE
$db->query("UPDATE oc_product SET
price = '" . (float)$row['price'] . "',
quantity = '" . (int)$row['quantity'] . "',
date_modified = NOW()
WHERE product_id = $product_id"
);
} else {
// INSERT + опис + категорії
// ...
}
}
$db->query("SET foreign_key_checks = 1");
$db->query("SET unique_checks = 1");
Запуск через cron: 0 6 * * * php /var/www/opencart/tools/import_products.php >> /var/log/oc_import.log 2>&1
Формати джерел
CSV від поставщика — найрозповсюджений. Проблеми: кодування (windows-1251 vs UTF-8), розділювач (; vs ,), нестандартні булеві значення (так/ні, 1/0, true/false).
Нормалізація перед імпортом:
# Конвертація кодування
iconv -f windows-1251 -t utf-8 feed_supplier.csv > feed_utf8.csv
# Заміна розділювача
sed 's/;/,/g' feed_utf8.csv > feed_normalized.csv
XML (YML — формат Яндекс.Маркет) — стандарт для російського ринку:
<offer id="SKU-001" available="true">
<name>Кофемашина DeLonghi ECAM 22.110</name>
<price>45990</price>
<currencyId>RUB</currencyId>
<categoryId>15</categoryId>
<picture>https://cdn.supplier.ru/img/ecam22110.jpg</picture>
<param name="Мощность">1450 Вт</param>
<param name="Объём бака">1.8 л</param>
</offer>
Парсинг через SimpleXML або XMLReader (для файлів > 50 МБ).
REST API поставщика — отримання даних по HTTP з пагінацією:
$page = 1;
do {
$response = json_decode(file_get_contents(
"https://api.supplier.ru/v2/products?page={$page}&per_page=200",
false,
stream_context_create(['http' => ['header' => "Authorization: Bearer {$token}\r\n"]])
), true);
foreach ($response['data'] as $item) {
// обробка товару
}
$page++;
} while ($response['meta']['current_page'] < $response['meta']['last_page']);
Експорт для зовнішніх систем
Выгрузка в Google Merchant Center (формат GMC):
// Генерація RSS/Atom фіду для GMC
header('Content-Type: application/xml; charset=utf-8');
echo '<?xml version="1.0" encoding="UTF-8"?>';
echo '<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">';
echo '<channel>';
$products = $db->query("
SELECT p.*, pd.name, pd.description
FROM oc_product p
JOIN oc_product_description pd ON pd.product_id = p.product_id
WHERE p.status = 1 AND pd.language_id = 1
LIMIT 5000
");
foreach ($products->rows as $p) {
echo '<item>';
echo '<g:id>' . $p['model'] . '</g:id>';
echo '<g:title><![CDATA[' . $p['name'] . ']]></g:title>';
echo '<g:price>' . number_format($p['price'], 2, '.', '') . ' RUB</g:price>';
echo '<g:availability>' . ($p['quantity'] > 0 ? 'in_stock' : 'out_of_stock') . '</g:availability>';
echo '</item>';
}
echo '</channel></rss>';
Обробка зображень
Завантаження зображень по URL — вузьке місце при масовому імпорту. Оптимальний підхід: черга + паралельна загрузка через curl_multi:
function downloadImagesParallel(array $urls, string $targetDir, int $concurrency = 10): array {
$mh = curl_multi_init();
$handles = [];
$results = [];
foreach (array_slice($urls, 0, $concurrency) as $url) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_FOLLOWLOCATION => true,
]);
curl_multi_add_handle($mh, $ch);
$handles[] = ['ch' => $ch, 'url' => $url];
}
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);
foreach ($handles as $item) {
$content = curl_multi_getcontent($item['ch']);
$filename = $targetDir . '/' . basename(parse_url($item['url'], PHP_URL_PATH));
file_put_contents($filename, $content);
$results[$item['url']] = $filename;
curl_multi_remove_handle($mh, $item['ch']);
}
curl_multi_close($mh);
return $results;
}
Валідація та логування
Кожен імпорт повинен мати звіт: скільки створено, оновлено, пропущено, з помилками. Мінімальна структура логу:
[2025-01-15 06:00:12] Import started: feed_2025-01-15.csv (4821 rows)
[2025-01-15 06:02:44] Created: 12, Updated: 4791, Skipped: 18, Errors: 0
[2025-01-15 06:02:44] Import finished in 152s
При помилках у рядку — запись в окремий файл import_errors.csv з номером рядка та описом проблеми.
Терміни
Налаштування готового модуля з маппінгом під конкретний формат поставщика: 1–2 дні. Кастомний скрипт з підтримкою XML/API, загрузкою зображень і логуванням: 3–5 днів. Повноцінна двостороння синхронізація з 1C або ERP: 1–3 тижні залежно від складності маппінгу даних.







