/** * Кастомные REST-методы для работы с SEO-полями разделов * ИСПОЛЬЗУЕТ ОФИЦИАЛЬНЫЙ API InheritedProperty для гарантии актуальности данных */ // Загружаем модуль инфоблоков \Bitrix\Main\Loader::includeModule('iblock'); /** * Регистрация кастомных методов */ function registerSeoRestMethods() { return [ 'custom.seo' => [ 'section.seo.list' => [ 'callback' => 'CustomSeoGetSectionsSeoList', 'options' => [] ], 'section.seo.update' => [ 'callback' => 'CustomSeoUpdateSectionSeo', 'options' => [] ] ] ]; } /** * Получить SEO-поля списка разделов (ОПТИМИЗИРОВАНО для массового аудита) * Параметры: IBLOCK_ID, FILTER[ID] (опционально), MAX_DEPTH (опционально) */ function CustomSeoGetSectionsSeoList($arParams) { $iblockId = intval($arParams['IBLOCK_ID'] ?? 0); $sectionIds = $arParams['FILTER']['ID'] ?? []; $maxDepth = intval($arParams['MAX_DEPTH'] ?? 0); if (!$iblockId) { return ['error' => 'IBLOCK_ID is required']; } // 1. Получаем базовые данные разделов через стандартный API $filter = ['IBLOCK_ID' => $iblockId]; if (!empty($sectionIds)) { $filter['ID'] = $sectionIds; } $select = ['ID', 'IBLOCK_SECTION_ID', 'DEPTH_LEVEL', 'NAME', 'CODE', 'DESCRIPTION', 'ACTIVE', 'LEFT_MARGIN', 'RIGHT_MARGIN']; $rs = \CIBlockSection::GetList( ['LEFT_MARGIN' => 'ASC'], $filter, false, $select ); $sections = []; while ($section = $rs->Fetch()) { if ($maxDepth > 0 && $section['DEPTH_LEVEL'] > $maxDepth) { continue; } // 2. Для каждого раздела получаем актуальные SEO-значения через официальный API $values = new \Bitrix\Iblock\InheritedProperty\SectionValues($iblockId, $section['ID']); $seoData = $values->getValues(); $sections[] = [ 'ID' => $section['ID'], 'IBLOCK_ID' => $iblockId, 'parent_id' => $section['IBLOCK_SECTION_ID'], 'DEPTH_LEVEL' => $section['DEPTH_LEVEL'], 'NAME' => $section['NAME'], 'CODE' => $section['CODE'], 'DESCRIPTION' => $section['DESCRIPTION'], 'ACTIVE' => $section['ACTIVE'], 'LEFT_MARGIN' => $section['LEFT_MARGIN'], 'RIGHT_MARGIN' => $section['RIGHT_MARGIN'], // Актуальные SEO-поля (могут быть null, если используется наследование без переопределения) 'seo_title' => $seoData['SECTION_META_TITLE'] ?? null, 'seo_keywords' => $seoData['SECTION_META_KEYWORDS'] ?? null, 'seo_description' => $seoData['SECTION_META_DESCRIPTION'] ?? null, 'h1' => $seoData['SECTION_PAGE_TITLE'] ?? null, 'seo_text' => $seoData['SECTION_SEO_TEXT'] ?? null, ]; } return $sections; } /** * Обновить SEO-поля раздела * Параметры: ID, IBLOCK_ID, SEO (массив полей) */ function CustomSeoUpdateSectionSeo($arParams) { $sectionId = intval($arParams['ID'] ?? 0); $iblockId = intval($arParams['IBLOCK_ID'] ?? 0); $seoData = $arParams['SEO'] ?? []; if (!$sectionId || !$iblockId) { return ['error' => 'ID and IBLOCK_ID are required']; } if (empty($seoData)) { return ['error' => 'SEO data is required']; } $section = \CIBlockSection::GetByID($sectionId)->Fetch(); if (!$section || $section['IBLOCK_ID'] != $iblockId) { return ['error' => 'Section not found or IBLOCK_ID mismatch']; } $fields = []; // Маппинг полей для CIBlockSection::Update (официальный способ) if (isset($seoData['seo_title'])) { $fields['SEO']['SECTION_META_TITLE'] = $seoData['seo_title']; } if (isset($seoData['seo_keywords'])) { $fields['SEO']['SECTION_META_KEYWORDS'] = $seoData['seo_keywords']; } if (isset($seoData['seo_description'])) { $fields['SEO']['SECTION_META_DESCRIPTION'] = $seoData['seo_description']; } if (isset($seoData['h1'])) { $fields['SEO']['SECTION_PAGE_TITLE'] = $seoData['h1']; } if (isset($seoData['seo_text'])) { $fields['SEO']['SECTION_SEO_TEXT'] = $seoData['seo_text']; } $bs = new \CIBlockSection(); $result = $bs->Update($sectionId, $fields); if ($result) { // Очищаем кеш SEO-значений после обновления (обязательно!) $values = new \Bitrix\Iblock\InheritedProperty\SectionValues($iblockId, $sectionId); $values->clearValues(); return ['success' => true, 'id' => $sectionId]; } else { return ['error' => $bs->LAST_ERROR]; } } // Регистрируем обработчик события AddEventHandler('rest', 'OnRestServiceBuildDescription', 'registerSeoRestMethods');
[RuntimeException] 
Could not start session because headers have already been sent. "/home/bitrix/www/local/php_interface/rest_seo_methods.php":1. (0)
/home/bitrix/www/bitrix/modules/main/lib/Session/Session.php:143
#0: Bitrix\Main\Session\Session->start
	/home/bitrix/www/bitrix/modules/main/lib/Session/KernelSessionProxy.php:47
#1: Bitrix\Main\Session\KernelSessionProxy->start
	/home/bitrix/www/bitrix/modules/main/include.php:151
#2: require_once(string)
	/home/bitrix/www/bitrix/modules/main/include/prolog_before.php:19
#3: require_once(string)
	/home/bitrix/www/bitrix/modules/main/include/prolog.php:10
#4: require_once(string)
	/home/bitrix/www/bitrix/header.php:2
#5: require(string)
	/home/bitrix/www/brands/detail.php:2
#6: include_once(string)
	/home/bitrix/www/bitrix/modules/main/include/urlrewrite.php:128
#7: include_once(string)
	/home/bitrix/www/bitrix/urlrewrite.php:2
----------