Автоматичне оновлення описів та характеристик товарів
При синхронізації товарів з XML-фіду постачальника описи та характеристики перезаписуються, втрачаючи ручні правки контент-менеджера. Це призводить до дублювання роботи та помилок. Ми реалізували систему роздільного зберігання даних з override-механізмом, яка автоматично завантажує дані, але пріоритет віддає ручним змінам. Такий підхід дозволяє обробляти до 100 000 товарів за 15 хвилин, що в 30 разів швидше ручного оновлення. За 7 років роботи ми реалізували понад 50 проєктів з синхронізації каталогів. Оцінимо ваш проєкт та запропонуємо оптимальне рішення.
Проблеми, які вирішуємо
- Перезапис ручних правок: якщо контент-менеджер вручну відредагував опис, автоматика не повинна його затирати. Рішення: розділення полів value і supplier_value з прапорцем is_manual_override.
- Різнорідні формати даних: кожен постачальник надсилає характеристики у своєму форматі. Необхідний нормалізатор, який приводить все до єдиної внутрішньої схеми.
- Обсяг даних: каталог з 100 000 товарів вимагає потокової обробки, щоб не впасти по пам'яті.
- Відсутність контролю: менеджери не бачать, що змінилося у постачальника, і не можуть прийняти або відхилити зміни.
Як працює система керованого оновлення?
Ключовий принцип: розділяти джерело даних (постачальник) і фінальний контент (що показується на сайті), з прапорцем «вручну відредаговано».
CREATE TABLE product_content ( product_id int REFERENCES products(id), source varchar(30), -- supplier_id або 'manual' field varchar(50), -- description | spec_weight | spec_color ... value text, is_manual_override boolean DEFAULT false, supplier_value text, -- останнє значення від постачальника updated_at timestamptz, PRIMARY KEY (product_id, field) ); При автооновленні: якщо is_manual_override = true — оновлювати тільки supplier_value, але не value. Контент-менеджер бачить розбіжність в інтерфейсі та вирішує, чи прийняти зміну постачальника. Така архітектура забезпечує гнучкість, підтверджену практикою.
Чому важливо розділяти джерело даних і фінальний контент?
Без розділення будь-яке автоматичне оновлення затирає ручні правки. Наш підхід з override-механізмом зберігає зміни редактора, а постачальник завжди бачить актуальні дані. Це критично, коли товарні позиції редагуються кількома людьми.
Джерела описів
XML-фід постачальника
Більшість виробничих компаній надають XML з розширеними атрибутами. Парсер на PHP читає файл потоково через XMLReader — це дозволяє обробляти каталоги будь-якого розміру без жадібності по пам'яті.
class XmlDescriptionSource implements DescriptionSourceInterface { public function fetch(): iterable { $xml = new \XMLReader(); $xml->open($this->url); while ($xml->read()) { if ($xml->nodeType === \XMLReader::ELEMENT && $xml->name === 'product') { $node = new \SimpleXMLElement($xml->readOuterXml()); yield $this->parseProduct($node); } } $xml->close(); } private function parseProduct(\SimpleXMLElement $node): array { $data = [ 'sku' => (string) $node['article'], 'description' => (string) $node->description, 'attributes' => [], ]; foreach ($node->attributes->attribute as $attr) { $data['attributes'][(string) $attr['name']] = (string) $attr; } return $data; } } API з частковим оновленням
Якщо постачальник надає endpoint змін, запит повертає тільки товари, у яких змінилося хоча б одне вказане поле — суттєво скорочує обсяг обробки.
Job-ланцюжок для оновлення контенту
Оновлення описів важче за оновлення цін — контент великий, потрібно нормалізувати атрибути, порівнювати з override-прапорцями. Оптимальна схема: окрема черга з низьким паралелізмом.
class UpdateProductDescriptionsJob implements ShouldQueue { public int $tries = 3; public int $backoff = 60; // секунди між повторами public function handle( DescriptionSourceInterface $source, AttributeNormalizer $normalizer, ContentUpdater $updater, ): void { foreach ($source->fetch() as $item) { $productId = Product::where('sku', $item['sku'])->value('id'); if (!$productId) continue; $updater->updateField($productId, 'description', $item['description']); foreach ($item['attributes'] as $name => $value) { $normalized = $normalizer->normalize($name, $value); if ($normalized) { $updater->updateField($productId, $normalized['key'], $normalized['value']); } } } } } Логіка ContentUpdater
class ContentUpdater { public function updateField(int $productId, string $field, mixed $newValue): void { $existing = ProductContent::where([ 'product_id' => $productId, 'field' => $field, ])->first(); if (!$existing) { ProductContent::create([ 'product_id' => $productId, 'field' => $field, 'value' => $newValue, 'supplier_value' => $newValue, ]); return; } $existing->supplier_value = $newValue; if (!$existing->is_manual_override) { $existing->value = $newValue; } $existing->updated_at = now(); $existing->save(); } } Розклад та пріоритети
| Тип даних | Частота | Причина |
|---|---|---|
| Характеристики (розміри, вага) | Раз на добу | Змінюються рідко |
| Описи | Раз на добу | Великий обсяг, не терміново |
| Статуси сертифікатів | Раз на тиждень | Змінюються ще рідше |
| Ціни | Кожні 15–30 хв | Висока волатильність |
Які ще джерела можна підключити?
Окрім XML та API, можлива інтеграція з CSV, JSON, Excel та прямим доступом до бази даних постачальника. Таблиця нижче порівнює основні способи.
| Джерело | Швидкість обробки | Складність реалізації |
|---|---|---|
| XML-фід | Висока (потокова) | Середня |
| REST API | Середня (залежить від лімітів) | Середня |
| CSV (S3) | Висока | Низька |
| SQL-репліка | Дуже висока | Висока |
Інтерфейс розбіжностей в адмінці
Якщо value != supplier_value AND is_manual_override = true, показувати в інтерфейсі товару попередження: «Постачальник змінив значення. Поточне: X, нове від постачальника: Y. Прийняти?» з кнопками «Прийняти» та «Залишити».
Типові проблеми при впровадженні
Поширені складнощі та їх вирішення
- Неповні фіди постачальника: іноді в XML відсутні обов'язкові атрибути. Рішення — налаштувати fallback на дефолтні значення або надсилати сповіщення.
- Змінилася структура фіду: без версіонування схеми парсер ламається. Хороша практика — перевіряти структуру при першому зверненні та логувати помилки.
- Конфлікт кодувань: UTF-8 vs Windows-1251. Нормалізатор повинен автоматично визначати кодування та конвертувати.
Що входить в роботу
- Проектування схеми даних та таблиці product_content
- Реалізація парсера для XML-фіду або API постачальника
- Нормалізатор атрибутів з мапінгом назв та типів
- Налаштування черг для фонового оновлення
- Інтерфейс розбіжностей в адмінці
- Тестування та документація
- Навчання контент-менеджерів
Зв'яжіться з нами для оцінки вашого проєкту — ми підберемо оптимальну архітектуру синхронізації. Замовте реалізацію автоматичного оновлення каталогу, і ваші менеджери перестануть витрачати час на рутинні правки.







