Перейти к содержимому

Правка структуры разделов - перенос, слияние, удаление

Перекраиваем дерево разделов на живом каталоге: переносим ветки, разводим товары и удаляем лишнее, не теряя элементы и не роняя адреса из поисковой выдачи.

Решение

Переносим раздел в другую ветку:

$section = new CIBlockSection();
$section->Update($sectionId, [
'IBLOCK_SECTION_ID' => $newParentId, // новый родитель, 0 - корень
'SORT' => 100,
]);
// адреса раздела и его товаров меняются вместе с веткой

Переезд ветки меняет адреса и самого раздела, и всех его подразделов с товарами. Это главное следствие: страницы, собранные по коду раздела, после переноса отвечают по новым адресам, а старые перестают существовать.

Перекидываем элементы между разделами:

CIBlockElement::SetElementSection($elementId, [$newSectionId], false);
// третий аргумент отвечает за проверку прав, false ускоряет массовую правку
$el = new CIBlockElement();
$el->Update($elementId, ['IBLOCK_SECTION_ID' => $newSectionId]); // основная привязка

Привязка к разделам и основная привязка элемента - разные вещи. Первая задаёт, где товар показывается, вторая - по какому разделу собирается его адрес, и править обычно нужно обе.

Удаляем раздел осознанно:

$res = CIBlockElement::GetList([], ['IBLOCK_ID' => 5, 'SECTION_ID' => $sectionId,
'INCLUDE_SUBSECTIONS' => 'Y'], []);
printf("в разделе элементов: %d\n", $res);
// удаление раздела удаляет и эти элементы: сначала переносим, потом удаляем
CIBlockSection::Delete($sectionId);

Удаление раздела уносит все его элементы вместе с ним. Порядок безопасной чистки один: сначала пересчитать и перенести товары, потом убедиться, что раздел пуст, и только затем удалять.

Проверяем адреса после переезда:

$res = CIBlockSection::GetList([], ['IBLOCK_ID' => 5, 'ID' => $sectionId], false,
['ID', 'NAME', 'SECTION_PAGE_URL', 'DEPTH_LEVEL']);
$row = $res->GetNext();
printf("%s -> %s (уровень %d)\n", $row['NAME'], $row['SECTION_PAGE_URL'], $row['DEPTH_LEVEL']);

Новый адрес собирается из шаблона адреса и кода раздела. Старые адреса при этом никуда не переезжают сами: переходы со старых на новые ставят руками, иначе выдача приводит посетителей на страницу с ошибкой.

Обмен с учётной системой вернёт правленую структуру обратно. Если разделы приезжают из неё, перекладывать дерево нужно на её стороне, а не на сайте, иначе первый же ночной сеанс отменит всю работу.

Правку структуры стоит делать в тихие часы и с готовой копией базы. Дерево разделов держит на себе адреса, фильтр и обмен, и ошибка в нём задевает сразу весь каталог, а не одну страницу.

После правки структуры обязательно пересобирают кэш и фасетный индекс. Витрина иначе показывает прежние ветки, а фильтр - прежние количества товаров по разделам.

Типичные проблемы

Вместе с разделом пропали все товары.

Удаление раздела удаляет вместе с ним и его элементы. Товары переносят в другой раздел до удаления, а не после него.

Ссылки из поиска ведут на страницу с ошибкой.

После переезда ветки адреса сменились, а переходы со старых не поставлены. Их прописывают вместе с самим переносом раздела.

Товар виден в разделе, но его адрес прежний.

Правилась привязка к разделам, а основная привязка осталась прежней. Адрес элемента собирается именно по основной привязке.

Наутро дерево вернулось к прежнему виду.

Разделы приезжают из учётной системы и переписываются при обмене. Структуру в этом случае правят на её стороне.

Фильтр показывает товары в старых разделах.

Фасетный индекс не пересобран после правки структуры каталога. Он хранит готовую связку значения свойства с разделом.

Частые вопросы

Как объединить два раздела?

Перенести элементы в один, проверить, что второй пуст, и удалить его. Прямого слияния разделов нет.

Можно ли держать товар сразу в нескольких разделах?

Да, привязок может быть несколько. Адрес при этом собирается по основной, а остальные влияют на показ в списках.

Что будет с сортировкой после переноса?

Значение поля сортировки остаётся прежним, а соседи меняются. Порядок в новой ветке обычно приходится задавать заново.

Как перенести сотню разделов сразу?

Скриптом по отбору с обходом порциями. Через интерфейс это делается по одному разделу.

Смежное

Первоисточник