[spoiler]
Постановка задачи
В издательстве используется "самописная" учетная система, в которой товары (в основном, книги) не имеют разделов-родителей, а обладают набором свойств - "жанр", "серия", "возраст", "бренд" и т.п.; при этом каждое значение свойства фактически является родителем для тех или иных товаров, например:
Книга "Огниво": жанр - "Художественная литература для детей", автор - "Андерсен", серия - "В гостях у сказки" |
Книга "Лунтик. Водная раскраска": тип - "Раскраска", жанр - "Подготовка к школе", бренд - "Лунтик" |
Идея
Как известно, в архитектуре "Битрикса" все рассчитано на то, что есть древовидная структура каталога (инфоблока) - разделы-родители и "вложенные" в них элементы (товары). Свойства в "Битриксе" не могут быть родителями элементов инфоблока. Но почему бы использовать значения свойств - в качестве названий разделов каталога? На основе этой идеи мы составили схему регулярного импорта данных из учетной системы издательства - в "Битрикс". Для того, чтобы отличать "ветки" каталога, созданные на основе свойств, мы использовали "хэштэги" наименований свойств - в качестве названий разделов. Часть схемы приведена ниже: красным - разделы 1-го уровня, оранжевым - разделы 2-го уровня ("хэштэги", созданные на основе свойств), желтым - разделы 3-го уровня, зеленым - товары.
Реализация
Поскольку каталог издательства создается и обновляется собственным скриптом импорта, мы добавили функции, которые создают и обновляют структуру разделов каталога на основе значений свойств товаров и привязывают товары к соответствующим разделам. Полные коды всех функций приводить здесь не буду, основных моментов два, (1) - привязка товаров c созданием новых разделов внутри "хэштэгов" и (2) - обновление структуры разделов:
Привязка товаров и создание новых разделов внутри "хэштэгов":
function SetElementHashSections($arElement,$arProperties,$arBrand) { $arHashSectionsResult = array('RESULT'=>true,'MESSAGE'=>''); if($arElement['IBLOCK_SECTION_ID']) { if(!is_array($arElement['IBLOCK_SECTION_ID'])) $arElementGroups = $arElement['IBLOCK_SECTION_ID'] = array($arElement['IBLOCK_SECTION_ID']); else $arElementGroups = $arElement['IBLOCK_SECTION_ID']; foreach($arElement['IBLOCK_SECTION_ID'] as $iblock_section_id) { $nav = CIBlockSection::GetNavChain(false, $iblock_section_id); while($ar_nav = $nav->GetNext()) $sect_path[] = $ar_nav['ID']; $rsHashSections = CIBlockSection::GetList( array(), array( "NAME"=>"#%", "SECTION_ID"=>$sect_path[0], "IBLOCK_ID"=>$arElement['IBLOCK_ID'] ) ); while($arHashSection = $rsHashSections->GetNext()) { $arHashName = explode('/',$arHashSection['NAME']); $arHashName[0] = substr($arHashName[0],1); foreach($arHashName as $depth=>$hashname) { $PropCode = $arProperties[$hashname]; if($PropCode == 'BRAND') $PropValue = $arBrand[$arElement['PROPERTY_VALUES'][$PropCode]]; else $PropValue = $arElement['PROPERTY_VALUES'][$PropCode]; if($PropCode && $PropValue) { if(is_array($PropValue)) $arPropValue=$PropValue; else $arPropValue=array($PropValue); foreach($arPropValue as $PropValue) { $rsHashSubSection = CIBlockSection::GetList( array(), array( "=NAME" => $PropValue, "SECTION_ID" => ($depth == 0)? $arHashSection['ID']:$subsection_parent_id, "IBLOCK_ID"=>$arElement['IBLOCK_ID'] ) ); if($arHashSubSection = $rsHashSubSection->GetNext()) { $arElementGroups[] = $subsection_id = $arHashSubSection["ID"]; } else { $bs = new CIBlockSection; $subsection_id = $bs->Add(array( "ACTIVE" => 'Y', "NAME" => $PropValue, "CODE" => GetSymCode($PropValue), "IBLOCK_SECTION_ID" => ($depth == 0)? $arHashSection['ID']:$subsection_parent_id, "IBLOCK_ID" => $arElement['IBLOCK_ID'] )); if($subsection_id) { $arElementGroups[] = $subsection_id; $arHashSectionsResult = array( 'RESULT' => true, 'MESSAGE' => "Создан подраздел \"". $PropValue. "\" внутри хэштэга ".$arHashSection['NAME']."\n" ); } else $arHashSectionsResult = array( 'RESULT' => false, 'MESSAGE' => "Создание подраздела \"". $PropValue. "\" внутри хэштэга ".$arHashSection['NAME']." не получилось: ". $bs->LAST_ERROR."\n" ); } } } if($depth == 0) $subsection_parent_id = $subsection_id; } } } if(count($arElementGroups)>1) CIBlockElement::SetElementSection($arElement['ID'], $arElementGroups); } return $arHashSectionsResult; } |
function MakeHashSubSectionsActive($IBLOCK_ID) { $rsHashSections = CIBlockSection::GetList(array(),array("NAME"=>"#%","DEPTH_LEVEL"=>2,"IBLOCK_ID"=>$IBLOCK_ID)); while($arHashSection = $rsHashSections->GetNext()) { $rsHashSubSection = CIBlockSection::GetList( array(), array( "SECTION_ID"=>$arHashSection['ID'], "IBLOCK_ID"=>$arElement['IBLOCK_ID'] ), true ); while($arHashSubSection = $rsHashSubSection->GetNext()) { if(!$arHashSubSection['ELEMENT_CNT'] && $arHashSubSection['ACTIVE']=='Y') { $bs = new CIBlockSection; $bs->Update($arHashSubSection['ID'], array("ACTIVE"=>"N")); echo "ОК Деактивирован подраздел \"".$arHashSubSection['NAME']."\" хэштэга ".$arHashSection['NAME']."\n"; } elseif($arHashSubSection['ELEMENT_CNT'] && $arHashSubSection['ACTIVE']=='N') { $bs = new CIBlockSection; $bs->Update($arHashSubSection['ID'], array("ACTIVE"=>"Y")); echo "ОК Активирован подраздел \"".$arHashSubSection['NAME']."\" хэштэга ".$arHashSection['NAME']."\n"; } } } } |