(подходит как для «старого» ядра, так и для D7)

Коротко:
- Делайте бэкап БД.
- Проверяйте, что у вашего пользователя есть право на удаление.
- Тестируйте код на копии сайта.
1. Почему элементы «ACTIVE = N» лучше чистить вручную
- Производительность. Чем меньше «мёртвых» записей, тем быстрее выборки.
- UX в админке. Сотрудникам проще ориентироваться в списках.
- SEO. Случайная переиндексация неактивных страниц = 404 + потеря краулингового бюджета.
2. Удаляем всё неактивное из инфоблока (старое ядро)
$iblockId,
'ACTIVE' => 'N'
];
$res = CIBlockElement::GetList([], $arFilter, false, false, ['ID']);
while ($element = $res->Fetch())
{
// true — успешное удаление, false — ошибка
$result = CIBlockElement::Delete((int)$element['ID']);
if(!$result)
{
global $APPLICATION;
echo "Ошибка при удалении элемента #{$element['ID']}: "
.$APPLICATION->LAST_ERROR."
";
}
}
3. Удаляем неактивные элементы только из выбранных разделов (старое ядро)
$iblockId,
'SECTION_ID' => $sectionIds,
'ACTIVE' => 'N',
'INCLUDE_SUBSECTIONS' => 'Y' // захватываем подразделы
];
$res = CIBlockElement::GetList([], $arFilter, false, false, ['ID']);
while ($el = $res->Fetch())
{
CIBlockElement::Delete((int)$el['ID']);
}
Лайфхак: если нужен только один раздел без подразделов — уберите INCLUDE_SUBSECTIONS
.
4. Современный способ на D7
4.1 Подготовка
use Bitrix\Iblock\Elements\ElementProductTable; // пример: high‑level ORM‑класс
use Bitrix\Iblock\Iblock; // вспомогательный класс для таблиц
use Bitrix\Main\Loader;
use Bitrix\Main\ORM\Query\Query;
Loader::includeModule('iblock');
ElementProductTable
- не забываем, что для использования такого класса, у вас должен быть определен соответствующий Символьный код API
в настройках инфоблока. В конкретном случае - product
. Если у вас она называется, к примеру, catalog
, то именем класса будет ElementCatalogTable
.
4.2 Удаляем из всего инфоблока
$iblockId = 7;
$iterator = ElementProductTable::query()
->setSelect(['ID'])
->where('IBLOCK_ID', $iblockId)
->where('ACTIVE', 'N')
->exec();
while ($row = $iterator->fetch())
{
\CIBlockElement::Delete((int)$row['ID']); // В D7 нет метода delete у ORM‑класса
}
Почему не$table::delete()
? У ORM‑классов инфоблоков нет полноценногоdelete()
, поэтому вызываем «старый» метод. Внутри 1С‑Битрикс он корректно удаляет файлы, свойства и записи в служебных таблицах.
4.3 Удаляем из конкретных разделов (D7 + Query)
$iblockId = 7;
$sectionIds = [12, 18, 24];
$query = new Query(ElementProductTable::getEntity());
$query->setSelect(['ID'])
->where('IBLOCK_ID', $iblockId)
->where('ACTIVE', 'N')
->whereIn('IBLOCK_SECTION_ID', $sectionIds)
->registerRuntimeField(
'SECTION',
[
'data_type' => '\Bitrix\Iblock\SectionTable',
'reference' => ['=this.IBLOCK_SECTION_ID' => 'ref.ID'],
'join_type' => 'INNER'
]
);
$result = $query->exec();
while ($row = $result->fetch())
{
CIBlockElement::Delete((int)$row['ID']);
}
Включаем подразделы D7‑ORM не умеет «из коробки» фильтровать по древовидной структуре. Нужно:
- Получить массив всех дочерних разделов через
Bitrix\Iblock\SectionTable::getList()
с фильтром поLEFT_MARGIN/RIGHT_MARGIN
.- Слить их в
$sectionIds
.- Использовать
whereIn()
как выше.
5. Массовое удаление через CLI скрипт (cron)
Создайте файл /local/scripts/clear_inactive.php
:
#!/usr/bin/php
<?php
$_SERVER['DOCUMENT_ROOT'] = realpath(__DIR__.'/../../'); // путь к корню сайта
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
// … любой из приведённых выше методов …
echo "Готово\n";
?>
Права:
chmod +x /local/scripts/clear_inactive.php
Cron‑задание (раз в неделю ночью):
0 3 * * 1 /local/scripts/clear_inactive.php
6. Транзакции и производительность
- Удалений много? Используйте
Bitrix\Main\Application::getConnection()->startTransaction();
и коммитьте каждые ~100 элементов. - Нужна атомарность? Откатите транзакцию
rollback()
при первой ошибке. - Больше 5 000 элементов? Запускайте скрипт через CLI или
php -d memory_limit=1G
.
7. Частые ошибки
Ошибка | Причина | Решение |
---|---|---|
You don't have permission to delete element |
Нет прав группы | Добавьте право «Удаление» в настройках инфоблока |
Скрипт «висит» | Ограничение max_execution_time |
Запускайте через CLI или увеличьте директиву |
Удалены элементы, но не файлы | Прямая работа через SQL | Используйте только API Bitrix |
8. Итоги
- Старое ядро удобно, когда нужно быстро и «в лоб».
- D7 даёт строгую типизацию, но пока не умеет удалять элементы напрямую — комбинируйте.
- Обязательно логируйте ошибки и держите резервную копию.
Теперь у вас есть полный набор рецептов, чтобы держать инфоблоки в идеальном порядке и не хранить «мертвые души». Успешной оптимизации!