| Цитата |
|---|
Ринат написал: Народ, привет. Подскажите, пожалуйста. Как я понимаю, во все случаях "ACTIVE" => "Y",это условие. А как сделать действие?. То есть нужно деактивировать товары с ценой ниже 10000 рублей во всех разделах имеющих url /catalog/konditsionery/ Кроме раздела, имеющий url /konditsionery/dopolnitelnoe_oborudovanie_dlya_konditsionero v/
Заранее спасибо! |
'FILTER_NAME' — это только «условие для выборки». Чтобы сделать действие (деактивировать элементы), нужно пройтись по подходящим товарам и обновить им поле 'ACTIVE' → 'N'.
Ниже — рабочий скрипт (CLI/однократный запуск), который:
- находит раздел konditsionery и все его подпункты,
- исключает из них подраздел dopolnitelnoe_oborudovanie_dlya_konditsionerov (вместе с его потомками),
- выбирает активные товары с ценой '< 10000' по базовому типу цены (ID=1),
- деактивирует их.
> ПОДСТАВЬТЕ свои '$iblockId' и при необходимости '$basePriceId'.
| Код |
|---|
<?php
use Bitrix\Main\Loader;
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
Loader::includeModule('iblock');
Loader::includeModule('catalog');
$iblockId = 2; // <-- ID инфоблока каталога
$basePriceId = 1; // <-- ID типа цены (обычно 1 — базовая)
$priceThreshold = 10000; // порог деактивации
$rootCode = 'konditsionery';
$excludeCode = 'dopolnitelnoe_oborudovanie_dlya_konditsionerov';
function getSectionByCode($iblockId, $code) {
$res = CIBlockSection::GetList(
[],
['IBLOCK_ID' => $iblockId, '=CODE' => $code],
false,
['ID','LEFT_MARGIN','RIGHT_MARGIN']
);
return $res->Fetch();
}
$root = getSectionByCode($iblockId, $rootCode);
$exclude = getSectionByCode($iblockId, $excludeCode);
if (!$root) {
die("Не найден раздел с CODE={$rootCode}\n");
}
// Список целевых разделов: все внутри $root, кроме поддерева $exclude
$targetSectionIds = [];
$secRes = CIBlockSection::GetList(
['LEFT_MARGIN' => 'ASC'],
[
'IBLOCK_ID' => $iblockId,
'>LEFT_MARGIN' => $root['LEFT_MARGIN'],
'<RIGHT_MARGIN' => $root['RIGHT_MARGIN'],
],
false,
['ID','LEFT_MARGIN','RIGHT_MARGIN']
);
while ($sec = $secRes->Fetch()) {
// пропускаем исключённое поддерево целиком
if ($exclude
&& $sec['LEFT_MARGIN'] >= $exclude['LEFT_MARGIN']
&& $sec['RIGHT_MARGIN'] <= $exclude['RIGHT_MARGIN']
) {
continue;
}
$targetSectionIds[] = (int)$sec['ID'];
}
// при необходимости включаем сам корневой раздел
$targetSectionIds[] = (int)$root['ID'];
$targetSectionIds = array_values(array_unique($targetSectionIds));
if (empty($targetSectionIds)) {
die("Не найдено целевых разделов\n");
}
// Выбираем активные товары с ценой ниже порога
$filter = [
'IBLOCK_ID' => $iblockId,
'ACTIVE' => 'Y', // чтобы не трогать уже неактивные
'SECTION_ID' => $targetSectionIds,
'INCLUDE_SUBSECTIONS' => 'N', // мы уже развернули список всех нужных разделов
'<CATALOG_PRICE_'.$basePriceId => $priceThreshold,
// 'CHECK_PERMISSIONS' => 'N', // раскомментируйте при запуске из CLI, если нужно игнорировать права
];
$el = new CIBlockElement();
$rs = CIBlockElement::GetList(
['ID' => 'ASC'],
$filter,
false,
false,
['ID']
);
$deactivated = 0;
while ($item = $rs->Fetch()) {
$ok = $el->Update($item['ID'], ['ACTIVE' => 'N']);
if ($ok) {
$deactivated++;
} else {
echo "Ошибка для ID {$item['ID']}: {$el->LAST_ERROR}\n";
}
}
echo "Деактивировано товаров: {$deactivated}\n"; |
Важные нюансы
- Тип цены: в фильтре используется 'CATALOG_PRICE_<ID_типа_цены>'. Если сравнивать нужно не по базовой, замените '$basePriceId'.
- SKU (оферы): если цены лежат на оферах, а выключать нужно родительские товары, то простой фильтр по 'CATALOG_PRICE_*' вернёт оферы, а не родителя. В таком случае:
1) получите оферы с ценой '< 10000' и их 'PRODUCT_ID' (ID родителя),
2) деактивируйте родителей по списку 'PRODUCT_ID' (или сами оферы — как нужно по задаче).
- Тестовый прогон: прежде чем обновлять, сделайте «dry-run»: вместо '$el->Update(...)' просто выводите ID и проверьте, что выборка корректна.
- Производительность: при большом каталоге запускайте в CLI (php -d short_open_tag=On -f script.php) и по возможности батчами.