Автоматичне оновлення описів та характеристик товарів
При синхронізації товарів з 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 постачальника
- Нормалізатор атрибутів з мапінгом назв та типів
- Налаштування черг для фонового оновлення
- Інтерфейс розбіжностей в адмінці
- Тестування та документація
- Навчання контент-менеджерів
Зв'яжіться з нами для оцінки вашого проєкту — ми підберемо оптимальну архітектуру синхронізації. Замовте реалізацію автоматичного оновлення каталогу, і ваші менеджери перестануть витрачати час на рутинні правки.







