Answer the question
In order to leave comments, you need to log in
How to make adding products to cart only from one parent category?
Hello.
It is necessary to make sure that only products from the main parent category can be added to the cart.
At the same time, take into account that a product can be added to several subcategories at once, which are located in different parent categories.
Let's say the categories are:
function getParent($id) {
$tt = CIBlockSection::GetList([], array('ID' => $id));
$as = $tt->GetNext();
static $a;
if ($as['DEPTH_LEVEL'] == 1)
$a = $as['ID'];
else
getParent($as['IBLOCK_SECTION_ID']);
return $a;
}
$currentElement = CIBlockElement::GetList([], [
"IBLOCK_ID" => $_REQUEST["iblockID"],
"ID" => $_REQUEST["item"]
]);
$ob = $currentElement->GetNextElement();
echo getParent($ob->GetFields()['IBLOCK_SECTION_ID']);
Answer the question
In order to leave comments, you need to log in
Let's talk a little about something else.
Suppose you have the following structure:
Moscow (id: 1)
Devices (id: 2)
Tools (id: 5)
St. Petersburg (id: 3)
Tools (id: 4)
If a product belongs to category 5, then it is from Moscow and, accordingly, when adding a product from id: 2, it should be added.
And if you have the goods at the same time and there and there? Well, let's say the product was added to both id:4 and id:5 - the situation can be like this. In your code, if the product was listed in this way, then when adding the parent section, it can be both St. Petersburg and Moscow, then your logic will not work in one of the cities, and this is wrong.
I sketched a couple of examples here and made a couple of assumptions:
1) Some product is already in the cart
2) You already know the ID of the city from which the product was added to the cart
The whole code (without magic) responsible for checking the ability to add a product:
/**
* @var integer Идентификатор товара из CITY_PRODUCTS_IBLOCK_ID, добавляемого в корзину
*/
$iProductId = 650;
/**
* @var integer Идентификатор города, товар которого уже добавлен в корзину
*/
$iCityId = 91;
if ( canAddByCity($iProductId, $iCityId) )
{
echo "Можно добавить";
}
else
{
echo "Нельзя добавить";
}
/**
* @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;
}
The product has a main section to which it is attached, it can be changed through the admin panel ( https://dev.1c-bitrix.ru/learning/course/?COURSE_I... Therefore, when you receive a parent section for a product, you will always receive one and the same main section.As mentioned above, you need to look at the section in which the user is now, if it does not match the main section of the product, then such a product should not be added to the basket
you can immediately see the level of typical "bitrixoids".
in general, as I understand it, ajax, adding to the cart, and you know nothing but the id of the product in the script.
Of course, you can use all sorts of CIBlockElement::GetElementGroups and CIBlockSection::GetNavChain, but this will lead to a lot of requests in a cycle, the larger the section, the more requests and the slower everything works.
I understand that you need to find out all the parent categories of the first level, knowing only the product id.
we look at the sources of the Bitrix core, and we understand that
b_iblock_section is a section table
b_iblock_section_element is a table of elements and sections links
Way to store the section tree in Bitrix - nested sets
google what it is, read it and figure it out, believe me, this is more useful information than remembering the ancient Bitrix api,
and having figured it out, with one request from the database we get all the first-level categories to which the product is linked, even if it is not tied specifically to these categories, and is tied to subcategories of these categories of the first level
select
s.ID
from b_iblock_section_element se
inner join b_iblock_section l
on l.ID = se.IBLOCK_SECTION_ID
inner join b_iblock_section s
on s.IBLOCK_ID = l.IBLOCK_ID
and s.LEFT_MARGIN <= l.LEFT_MARGIN
and s.RIGHT_MARGIN >= l.RIGHT_MARGIN
and s.DEPTH_LEVEL = 1
where se.iblock_element_id = 2212954
group by s.ID
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question