Давай поговорим немножко о другом.
Предположим, что у тебя следующая структура:
Москва (id: 1)
Приборы (id: 2)
Инструменты (id: 5)
Санкт-Петербург (id: 3)
Инструменты (id: 4)
Если товар принадлежит к категории 5, то он точно из Москвы и соответственно при добавлении товара из id:2 он должен добавиться.
А если товар у тебя есть одновременно и там и там? Ну скажем, товар был добавлен и в id:4 и в id:5 - ситуация может быть и такой. В твоем коде, если товар так был занесен, то при добавлении родительский раздел может быть как СПБ, так и Москва, тогда в одном из городов твоя логика работать не будет, а это неправильно.
Я тут набросал пару примеров и сделал пару допущений:
1) Какой-то товар уже в корзине
2) Ты уже знаешь ID города, товар из которого добавлен в корзину
Весь код (без магии), отвечающий за проверку возможности добавлять товар:
/**
* @var integer Идентификатор товара из CITY_PRODUCTS_IBLOCK_ID, добавляемого в корзину
*/
$iProductId = 650;
/**
* @var integer Идентификатор города, товар которого уже добавлен в корзину
*/
$iCityId = 91;
if ( canAddByCity($iProductId, $iCityId) )
{
echo "Можно добавить";
}
else
{
echo "Нельзя добавить";
}
Как видишь, в этом коде нет ничего интересного. Вся магия начинается в функции canAddByCity (да-да, написано не оптимально, нужно оптимизировать и т.п. и т.д. но для пояснения сойдет):
/**
* @var int Уровень вложенности, где находятся города (у меня 2)
*/
define('CITY_DEPTH_LEVEL', 2);
/**
* @var integer Идентификатор инфоблока, где ищем товары
*/
define('CITY_PRODUCTS_IBLOCK_ID', 5);
/**
* Возвращает true, если товар $product можно добавить в корзину
* @param integer $product
* @param integer $city
* @return boolean
*/
function canAddByCity( $product, $city = 0 )
{
if ( empty($city) )
{
return true;
}
if ( !\Bitrix\Main\Loader::IncludeModule('iblock') )
{
return false;
}
/**
* @var array Список категорий верхнего уровня для сравнения
*/
$arRootGroups = [];
/**
* @var CDBResult
* @see https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/getelementgroups.php
*/
$resGroups = \CIBlockElement::GetElementGroups($product, true);
while( $arGroup = $resGroups->fetch() )
{
/**
* А вдруг товар без категории и сразу добавлен в город
* т.е. без привязки?
*/
if ( $arGroup['DEPTH_LEVEL'] == \CITY_DEPTH_LEVEL )
{
$arRootGroups[] = $arGroup['ID'];
continue;
}
/**
* @todo Запросы в цикле это очень плохо.
* Лучше запомнить где-то разделы и лишние уровни и дополнительным
* циклом пройтись после - запросов будет меньше и будет быстрее работать
*/
$iRootSectionId = getSectionIdByDepthLevel($arGroup['ID']);
if ( !empty($iRootSectionId) )
{
$arRootGroups[] = $iRootSectionId;
continue;
}
}
// Какие корневые группы имеет этот товар
// можно посмотреть через код
//var_dump($arRootGroups);
return in_array($city, $arRootGroups);
}
/**
* Возвращает код родительского раздела $section из инфоблока $iblockId
* на уровне CITY_DEPTH_LEVEL. В случае отсутствия возвращает 0
* @param integer $section
* @param integer $iblockId
* @return integer
*/
function getSectionIdByDepthLevel( $section, $iblockId = \CITY_PRODUCTS_IBLOCK_ID )
{
$section = intval($section);
if ( empty($section) )
{
return 0;
}
if ( empty($iblockId) )
{
return 0;
}
if ( !\Bitrix\Main\Loader::IncludeModule('iblock') )
{
return 0;
}
$resChain = \CIBlockSection::GetNavChain($iblockId, $section, ['ID','DEPTH_LEVEL','IBLOCK_SECTION_ID']);
while( $arSection = $resChain->fetch() )
{
if ( $arSection['DEPTH_LEVEL'] == \CITY_DEPTH_LEVEL)
{
return $arSection['ID'];
}
}
return 0;
}