Изменение категорий(секций/разделов) товаров при выгрузки из 1с в битрикс.

// Массив для замен категорий товаров в процессе переноса и обновления данных из 1С

$arReplace_RND_735jYx = array(// Под ID понимается категория с которой осуществляется работа, а не её родитель. Так же под EXTERNAL_ID и NAME подразумеваются значения текущей секции/категории, а не её родителя. В out под теми же именами массива понимаются значения категории/секции с которой идёт сопоставление.Если значение не известно его можно оставить пустым или присвоить ему false или можно его не описывать в массиве - ошибки так же не будет.

array("in"=>array("ID"=>false,"EXTERNAL_ID"=>"5926a1ef-afe3-11e7-9151-0025226dfab1","NAME"=>"ГОРЕЛКИ, ПЛИТКИ, ГАЗ"),"out"=>array("ID"=>4910,"EXTERNAL_ID"=>false,"NAME"=>false))

);

// Это вспомогательная функция - она определяет Id секции/категории, на которую нужно переопределить текущую категорию у товара в процессе синхронизации с 1С. Напрямую данная функция в обработчиках событий не используется.

function myGetSectionIdForReplace_RND_352kTn($checkid = false) {

$one = true;

$outsectionid = false;// В эту переменную подставится нужное значение секции/категории или так и будет возвращено значение false

$ar_res = array();// Эту переменную с точки зрения PHP объявлять не обязательно, но в C# - переменная объявляется не ниже уровня в котором используется. придерживаюсь этого правила, можно удалть эту строчку ничего не изменися - проверка на E_notice на всякйий случай реализована уровнем ниже.

if ($checkid) {

if(CModule::IncludeModule("iblock")) {

$res = CIBlockSection::GetByID($checkid);

if (isset($GLOBALS["arReplace_RND_735jYx"])) {

$arreplace = $GLOBALS["arReplace_RND_735jYx"];

}

while (// Что за условия ниже я прокоментирую

(($one === true) and ($res !== false) and (($ar_res = $res->GetNext()) !== false)) or//Если первый проход цикла $res уже получен, создаётся $ar_res как GetNext метод $res, $ar_res проверяется на возврат false

(($one === false) and isset($ar_res["IBLOCK_SECTION_ID"]) and (($res = CIBlockSection::GetByID($ar_res["IBLOCK_SECTION_ID"])) !== false) and (($ar_res = $res->GetNext()) !== false))// Последующие проходы цикла - проверяем существование $ar_res["IBLOCK_SECTION_ID"], если есть создаём от него $res, $res проверяем на возврат false, далее от $res создаётся $ar_res, $ar_res так же проверяется на возврат false

) {

// $ar_res был создан в условии цикла, поэтому далее в теле цикла его не создаём, а сразу используем

if ($one === true) {$one = false;}// Если первый проход меняем значение переменной для последующих циклов

if (isset($arreplace) and is_array($arreplace)) {

foreach ($arreplace as $v) {

if ((isset($v["in"]["ID"]) and isset($ar_res["ID"]) and ($v["in"]["ID"] == $ar_res["ID"])) or (isset($v["in"]["EXTERNAL_ID"]) and isset($ar_res["EXTERNAL_ID"]) and ($v["in"]["EXTERNAL_ID"] == $ar_res["EXTERNAL_ID"])) or (isset($v["in"]["NAME"]) and isset($ar_res["NAME"]) and ($v["in"]["NAME"] == $ar_res["NAME"]))) {

if ($v["out"]["ID"]) {

$outsectionid = $v["out"]["ID"];

} elseif ($v["out"]["EXTERNAL_ID"] or $v["out"]["NAME"]) {

$qkey = "";

$qvalue = "";

if ($v["out"]["EXTERNAL_ID"]) {

$qkey = "EXTERNAL_ID";

$qvalue = $v["out"]["EXTERNAL_ID"];

} elseif ($v["out"]["NAME"]) {

$qkey = "NAME";

$qvalue = $v["out"]["NAME"];

}

if (($res2 = CIBlockSection::GetList(array("SORT"=>"ASC"),array($qkey=>$qvalue))) !== false) {

if (($ar_res2 = $res2->GetNext()) !== false) {

if (isset($ar_res2["ID"]) and $ar_res2["ID"]) {

$outsectionid = $ar_res2["ID"];

}

}

}

}

if ($outsectionid) {

break(2);

}

}

}

}

}

}

}

return $outsectionid;

}

// Создаём сами обработчики событий на добавление и изменение инфоблока

AddEventHandler("iblock", "OnAfterIBlockElementAdd", "myCheckProductSection");

AddEventHandler("iblock", "OnAfterIBlockElementUpdate", "myCheckProductSection");

// Обработчики ссылаются на функцию myCheckTovarSection создаём её

// Обратите внимание массив передаётся в функцию по ссылке(значёк &), это нужно для того, чтобы изменения внесённые в массив сохранились в базе данных(или как это называют в битрикс были присвоены соответствующему элементу инфоблока).

function myCheckProductSection(&$arFields) {

// внутри функции проверяем нужно ли переопределить ид секции(это то же самое что категория) для данного товара, и если требуется, то новое значение присваиваем массиву.

if ($newsection = myGetSectionIdForReplace_RND_352kTn($arFields["IBLOCK_SECTION"][0])) {

$ar["IBLOCK_SECTION"] = array($newsection);

}

}

Вы так же можете прочитать следующие статьи: