PHP
#bitrix#php#catalog#sku#cache#performance

Получить ID родительского товара по SKU (торговое предложение)

Быстрое получение ID родительского товара через CCatalogSku с кешированием результата для оптимизации.

Как использовать

  1. Подключите модуль catalog, используйте SkuTable::getList с filter ID и select PRODUCT_ID или CCatalogSku::GetProductInfo.
  2. Для снижения нагрузки кешируйте результат (Bitrix cache по cacheId = parent_product_{skuId}, директория /catalog/parent_product/).
  3. Передавайте ID торгового предложения (SKU); возвращается ID родительского товара или false.

В каталоге 1С-Битрикс у торгового предложения (SKU) есть связь с родительским товаром. Для ссылок на карточку товара, хлебных крошек, фильтров и API нужен ID родительского товара по ID предложения. Проблема: при каждом запросе ходить в БД за одной связью — лишняя нагрузка; в циклах по десяткам SKU получаются десятки запросов. Симптомы: медленные списки, дублирование запросов в логах. Ниже — получение ID родительского товара через D7 (SkuTable) с кешированием на час; проверка и когда использовать классический API.

Решение

Получение ID родительского товара по торговому предложению (SKU) через CCatalogSku с кешированием. Используйте когда нужно получить базовый товар из SKU без лишних запросов к БД.

use Bitrix\Main\Application;
use Bitrix\Main\Loader;
use Bitrix\Catalog\SkuTable;

/**
 * Получить ID родительского товара по SKU с кешем
 * @param int $skuId ID торгового предложения
 * @return int|false ID родительского товара или false
 */
function getParentProductIdBySku($skuId) {
    if (!Loader::includeModule('catalog')) {
        return false;
    }
    
    $cache = Application::getInstance()->getCache();
    $cacheId = 'parent_product_' . $skuId;
    $cacheDir = '/catalog/parent_product/';
    $cacheTtl = 3600; // 1 час
    
    if ($cache->initCache($cacheTtl, $cacheId, $cacheDir)) {
        $parentId = $cache->getVars();
    } elseif ($cache->startDataCache()) {
        $sku = SkuTable::getList([
            'filter' => ['=ID' => $skuId],
            'select' => ['PRODUCT_ID'],
            'limit' => 1
        ])->fetch();
        
        $parentId = $sku && $sku['PRODUCT_ID'] ? (int)$sku['PRODUCT_ID'] : false;
        $cache->endDataCache($parentId);
    } else {
        $parentId = false;
    }
    
    return $parentId;
}

Пример использования:

$skuId = 12345;
$parentId = getParentProductIdBySku($skuId);
if ($parentId) {
    $product = CIBlockElement::GetByID($parentId)->GetNext();
    // ссылка на карточку, хлебные крошки и т.д.
}

Используется SkuTable (D7) с полем PRODUCT_ID. Для старых версий Bitrix можно CCatalogSku::GetProductInfo($skuId); D7 предпочтительнее. Модуль catalog должен быть подключён.

Проверка

  1. SKU с известным родителем — в админке найдите торговое предложение и его родительский товар (ID). Вызовите getParentProductIdBySku(skuId); должен вернуться ID родительского элемента.

  2. Обычный товар (не SKU) — передайте ID элемента, который не является торговым предложением. Ожидаем false (в SkuTable записи по такому ID не будет).

  3. Кеш — дважды вызовите функцию с одним и тем же skuId; второй вызов не должен выполнять запрос к БД (проверьте по логам запросов или отключите кеш и сравните время). Очистка кеша: удаление директории кеша или сброс по тегу.

  4. Несуществующий skuId — передайте несуществующий ID; функция должна вернуть false.

Типичные ошибки

  • Не подключён модуль catalog — без Loader::includeModule(‘catalog’) SkuTable или GetProductInfo недоступны. Проверяйте возврат includeModule и при false возвращайте false из функции.
  • Кеш не инвалидируется при смене привязки — если связь SKU → товар в админке меняют редко, TTL 3600 достаточно; при частых изменениях уменьшите Ttl или сбрасывайте кеш по тегу при сохранении товара/SKU.
  • Перепутаны ID товара и SKU — в каталоге с торговыми предложениями элемент списка/корзины часто является SKU; родительский товар — другой элемент. Передавайте в функцию именно ID торгового предложения.

Где применять

  • Prod / dev: списки товаров, корзина, детальная страница SKU (ссылка на родителя, хлебные крошки), фильтры и API каталога, минификация запросов в циклах по SKU.
  • Когда не кешировать: если связь SKU↔товар меняется в рамках одного запроса или скрипта, можно вызывать SkuTable::getList без кеша.

Связанные сниппеты: Родительский товар по ID SKU (GetProductInfo), Список цен товара, Минимальная цена по типам цен.