Чаще всего поле остаётся пустым, когда не задан шаблон «URL страницы раздела» в настройках инфоблока — либо ваш скрипт читает данные не из того инфоблока. Ниже приведены четыре надёжных паттерна, которые быстро вернут рабочие ссылки и не сломаются при изменениях контента или настроек.

Зачем вообще нужен SECTION_PAGE_URL
- Формирует «чистый» адрес раздела («ЧПУ»), который любят пользователи и поисковые роботы.
- Лежит в основе хлебных крошек, sitemap.xml,
<canonical>
, а иногда и фильтров. - От него зависят такие компоненты, как
news.list
,catalog.section.list
,breadcrumb
, «Умный фильтр» и др.
Если поле пустое, компонент выводит относительный путь вида /bitrix/…/index.php?SECTION_ID=42
, что портит SEO-видимость и юзабилити.
Причины, по которым SECTION_PAGE_URL
оказывается пустым
Причина | Как диагностировать | Как лечить |
---|---|---|
Не задан шаблон URL | В админке пустое поле «URL страницы раздела» | Заполнить шаблон (см. способ 1) |
Код читает «не тот» инфоблок | $sec['IBLOCK_ID'] не совпадает с нужным |
Проверьте ID и права доступа |
Промежуточный кеш | В dev-режиме URL «есть», а на проде — нет | Очистите кеш или включите компонент «без кеша» на время теста |
Раздел без символического кода | В таблице b_iblock_section поле CODE — NULL |
Сгенерируйте символьные коды или включите автогенерацию |
1. Задаём шаблон URL в настройках инфоблока
- Контент → Инфоблоки → нужный инфоблок → Изменить.
- В блоке «URL страницы раздела» запишите, например:
#SITE_DIR#news/#SECTION_CODE_PATH#/
- Сохраните изменения и очистите кеш компонентов.
Проверочный код
<?php
$iblock = CIBlock::GetArrayByID($sec['IBLOCK_ID']);
$sec['SECTION_PAGE_URL'] = CIBlock::ReplaceDetailUrl(
$iblock['SECTION_PAGE_URL'], // ← шаблон, который вы только что задали
$sec,
true,
'S'
);
echo $sec['SECTION_PAGE_URL']; // /news/promo/akcija-20-proc/
?>
D7-вариант (короткий, без вызова «старыми» функциями):
use Bitrix\Iblock\Iblock;
use Bitrix\Iblock\Url\AdminPage\SectionAdminPageBuilder;
$iblock = Iblock::wakeUp($sec['IBLOCK_ID']);
$template = $iblock->getUrlTemplates()->getSectionUrlTemplate();
$builder = new SectionAdminPageBuilder($template);
$sec['SECTION_PAGE_URL'] = $builder->build(
['SECTION_CODE_PATH' => $sec['CODE_PATH']]
);
2. Когда шаблон менять нельзя — формируем URL вручную
Иногда шаблон «забит» под старую структуру, а прав на его редактирование нет. Самый безопасный путь — собрать URL программно:
<?php
use Bitrix\Iblock\SectionTable;
use CIBlockSection;
$sections = SectionTable::query()
->setSelect(['ID', 'IBLOCK_ID', 'CODE'])
->whereIn('ID', $ids) // $ids — нужные ID разделов
->fetchCollection();
foreach ($sections as $section)
{
// 1. Получаем цепочку родителей
$chain = CIBlockSection::GetNavChain(
$section->getIblockId(),
$section->getId(),
['CODE']
);
// 2. Склеиваем символьные коды
$codes = [];
while ($row = $chain->Fetch())
$codes[] = $row['CODE'];
// 3. Собираем финальный URL
$section['SECTION_PAGE_URL'] = '/news/' . implode('/', $codes) . '/';
}
?>
Плюсы метода
- Не зависит от настроек инфоблока: даже если админ очистит шаблон, ссылка продолжит строиться.
- Логика «в одном месте» — удобно поддерживать.
Минусы
- Один доп-запрос
GetNavChain
на каждый раздел. Решается кешем или батч-запросом.
3. Быстрый «костыль» — ставим фолбэк, если шаблон пуст
Подходит для существующих проектов, где страшно что-то менять.
<?php
$iblock = CIBlock::GetArrayByID($sec['IBLOCK_ID']);
$template = $iblock['SECTION_PAGE_URL'];
if ($template) // шаблон есть → используем стандартный путь
{
$sec['SECTION_PAGE_URL'] = CIBlock::ReplaceDetailUrl(
$template,
$sec,
true,
'S'
);
}
else // шаблона нет → надёжный фолбэк
{
$sec['SECTION_PAGE_URL'] = '/news/' . $sec['CODE'] . '/';
}
?>
Совет: добавьте логирование в ветку else
— так вы узнаете, кто и когда «сломал» шаблон.
4. Расширенный подход — собственный хелпер
Чтобы не дублировать логику, вынесите всё в одну функцию и подключайте через Composer-автолоадер или Bitrix-модуль:
<?php
namespace My\Tools;
use Bitrix\Iblock\SectionTable;
use CIBlockSection;
use CIBlock;
class Url
{
public static function getSectionUrl(array $section, string $base = '/news/'): string
{
static $cache = [];
$iblockId = $section['IBLOCK_ID'];
// 1. Пробуем шаблон
if (!isset($cache[$iblockId]))
{
$iblock = CIBlock::GetArrayByID($iblockId);
$cache[$iblockId] = $iblock['SECTION_PAGE_URL'];
}
$template = $cache[$iblockId];
if ($template)
{
return CIBlock::ReplaceDetailUrl($template, $section, true, 'S');
}
// 2. Фолбэк — ручная сборка пути
$chain = CIBlockSection::GetNavChain(
$iblockId,
$section['ID'],
['CODE']
);
$codes = [];
while ($row = $chain->Fetch())
$codes[] = $row['CODE'];
return $base . implode('/', $codes) . '/';
}
}
?>
Использование:
$url = \My\Tools\Url::getSectionUrl($sec);
Чек-лист перед публикацией
- Убедитесь, что у всех разделов проставлен символьный код (
CODE
). - Очистите кеш компонентов и меню после изменения шаблона.
- Если применяете способ 2 или 3, проверьте нагрузку на БД и при необходимости закешируйте
GetNavChain
. - Включите «Отладку композиций URL» в
/bitrix/.settings.php
, чтобы ловить ошибки ещё на dev-стенде.
Итоги
- Базовое решение — задать правильный шаблон в инфоблоке.
- Гарантированное решение — формировать URL самостоятельно, отталкиваясь от
SECTION_CODE_PATH
. - Продвинутое решение — вынести генерацию URL в общий хелпер и кешировать результаты.
Так вы защитите проект от случайных ошибок контент-менеджеров, не потеряете позиции в поиске и избавитесь от битых хлебных крошек.