Автоматизация переноса товаров между категориями при синхронизации с 1С
Для чего нужен этот код?
При интеграции интернет-магазина на Битрикс с системой 1С часто возникает необходимость переносить товары из одних категорий в другие. Это может потребоваться в нескольких случаях:
-
Реорганизация структуры каталога - когда категории в интернет-магазине не совпадают с категориями в 1С
-
Объединение разделов - если в 1С товары разнесены по разным категориям, а на сайте должны находиться в одной
-
Изменение структуры - при изменении логики категоризации товаров на сайте
-
Исправление ошибок - когда товары по ошибке попадают не в те разделы
Как работает решение?
Представленный код решает эти задачи следующим образом:
-
Гибкое сопоставление категорий - можно задавать соответствия по:
-
ID категории
-
Внешнему коду (EXTERNAL_ID)
-
Названию категории (NAME)
-
-
Автоматическая обработка - система сама находит нужные товары и перемещает их в указанные категории при:
-
Добавлении нового товара
-
Обновлении существующего товара
-
-
Простое управление - все настройки хранятся в одном понятном массиве, где можно указать:
-
Какие категории искать (входные параметры)
-
В какие категории переносить (выходные параметры)
-
Преимущества решения
-
Экономия времени - не нужно вручную перемещать сотни товаров
-
Минимизация ошибок - автоматизация исключает человеческий фактор
-
Гибкость - можно настроить любые правила переноса
-
Совместимость - работает со стандартными механизмами Битрикс
-
Простота обновления - правила переноса легко дополнять и изменять
Это решение особенно полезно для крупных интернет-магазинов с постоянно обновляемым ассортиментом, где ручной перенос товаров между категориями занимал бы слишком много времени.
<?php
/**
* Массив для замены категорий товаров при переносе данных из 1С
* @var array $arReplaceCategories Массив сопоставления категорий (in - исходная, out - целевая)
*/
$arReplaceCategories = array(
array(
"in" => array(
"EXTERNAL_ID" => "5926a1ef-afe3-11e7-9151-0025226dfab1",
"NAME" => "ГОРЕЛКИ, ПЛИТКИ, ГАЗ"
),
"out" => array(
"ID" => 4910
)
)
);
/**
* Определяет ID категории для замены при синхронизации с 1С
* @param int|bool $checkId ID проверяемой категории
* @return int|bool ID новой категории или false если замена не требуется
*/
function getReplacementSectionId($checkId = false) {
$replacementId = false;
if ($checkId && CModule::IncludeModule("iblock")) {
$section = CIBlockSection::GetByID($checkId);
$sectionData = $section->GetNext();
if ($sectionData) {
global $arReplaceCategories;
foreach ($arReplaceCategories as $replacement) {
$matchFound = false;
// Проверка совпадения по ID
if (isset($replacement["in"]["ID"]) && $replacement["in"]["ID"] == $sectionData["ID"]) {
$matchFound = true;
}
// Проверка совпадения по EXTERNAL_ID
elseif (isset($replacement["in"]["EXTERNAL_ID"]) && $replacement["in"]["EXTERNAL_ID"] == $sectionData["EXTERNAL_ID"]) {
$matchFound = true;
}
// Проверка совпадения по NAME
elseif (isset($replacement["in"]["NAME"]) && $replacement["in"]["NAME"] == $sectionData["NAME"]) {
$matchFound = true;
}
if ($matchFound) {
// Если указан ID для замены
if ($replacement["out"]["ID"]) {
return $replacement["out"]["ID"];
}
// Если указаны другие параметры для поиска новой категории
elseif ($replacement["out"]["EXTERNAL_ID"] || $replacement["out"]["NAME"]) {
$filterField = $replacement["out"]["EXTERNAL_ID"] ? "EXTERNAL_ID" : "NAME";
$filterValue = $replacement["out"]["EXTERNAL_ID"] ?: $replacement["out"]["NAME"];
$newSection = CIBlockSection::GetList(
array("SORT" => "ASC"),
array($filterField => $filterValue)
)->GetNext();
if ($newSection && $newSection["ID"]) {
return $newSection["ID"];
}
}
}
}
}
}
return $replacementId;
}
// Регистрация обработчиков событий
AddEventHandler("iblock", "OnAfterIBlockElementAdd", "updateProductSection");
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", "updateProductSection");
/**
* Обновляет категорию товара при добавлении/изменении
* @param array $arFields Поля элемента инфоблока
*/
function updateProductSection(&$arFields) {
if (!empty($arFields["IBLOCK_SECTION"][0])) {
if ($newSectionId = getReplacementSectionId($arFields["IBLOCK_SECTION"][0])) {
$arFields["IBLOCK_SECTION"] = array($newSectionId);
}
}
}
?>Представленное решение автоматизирует процесс синхронизации категорий товаров между 1С и Битрикс, что особенно важно для:
-
Крупных интернет-магазинов с частыми обновлениями ассортимента.
-
Проектов с реорганизацией структуры каталога, где требуется массовый перенос товаров.
-
Интеграций, где категории в 1С и на сайте не совпадают, но должны быть приведены к единой структуре.
Рекомендации по улучшению и доработке
1. Добавление логирования изменений
AddEventHandler("main", "OnAfterEventLog", function($event, $lid, $arFields) {
$logMessage = date('Y-m-d H:i:s') . " | Товар ID: {$arFields['ID']} | ";
$logMessage .= "Старая категория: {$arFields['IBLOCK_SECTION'][0]} | ";
$logMessage .= "Новая категория: {$newSectionId}\n";
file_put_contents(
$_SERVER['DOCUMENT_ROOT'] . '/upload/category_changes.log',
$logMessage,
FILE_APPEND
);
});2. Кэширование запросов к категориям
$cache = Bitrix\Main\Data\Cache::createInstance();
$cacheTime = 3600;
$cacheID = 'section_data_' . $checkId;
if ($cache->initCache($cacheTime, $cacheID)) {
$sectionData = $cache->getVars();
} elseif ($cache->startDataCache()) {
$section = CIBlockSection::GetByID($checkId);
$sectionData = $section->GetNext();
$cache->endDataCache($sectionData);
}3. Многоуровневая проверка категорий
// Добавить в функцию getReplacementSectionId
if ($sectionData['IBLOCK_SECTION_ID']) {
$parentSection = CIBlockSection::GetByID($sectionData['IBLOCK_SECTION_ID']);
if ($parentData = $parentSection->GetNext()) {
// Проверка родительской категории
}
}4. Обработка множественных категорий
// Модификация функции updateProductSection
if (!empty($arFields["IBLOCK_SECTION"])) {
$newSections = array();
foreach ($arFields["IBLOCK_SECTION"] as $sectionId) {
if ($newId = getReplacementSectionId($sectionId)) {
$newSections[] = $newId;
} else {
$newSections[] = $sectionId;
}
}
$arFields["IBLOCK_SECTION"] = array_unique($newSections);
}Дополнительные возможности для расширения
-
Интеграция с административным интерфейсом
-
Создание отдельного модуля для управления правилами замены
-
Визуальный редактор соответствий категорий
-
-
Пакетная обработка существующих товаров
$res = CIBlockElement::GetList( array(), array("IBLOCK_ID" => $iblockId), false, false, array("ID", "IBLOCK_SECTION") ); while ($elem = $res->GetNext()) { updateProductSection($elem); }
-
Проверка дубликатов товаров
$checkDublicate = CIBlockElement::GetList( array(), array( "!ID" => $arFields["ID"], "IBLOCK_ID" => $arFields["IBLOCK_ID"], "IBLOCK_SECTION_ID" => $newSectionId, "NAME" => $arFields["NAME"] ) )->Fetch();
Заключение
Представленное решение позволяет автоматизировать процесс синхронизации категорий между 1С и Битрикс, значительно экономя время администраторов. Код готов к использованию и может быть легко расширен под конкретные задачи вашего проекта.
Дальнейшие шаги для внедрения:
-
Настроить массив $arReplaceCategories под вашу структуру каталога
-
Протестировать на тестовой площадке
-
Добавить необходимое логирование
-
Реализовать дополнительные проверки при необходимости
Для сложных интеграций рекомендуем обратиться к специалистам по Битрикс, которые помогут адаптировать решение под ваши бизнес-процессы.