Создание агента в 1С-Битрикс, на реальном примере

Просмотров: 350

Задача: Каждый час нужно обновлять свойство элементов/товаров с типом строка "В наличии", вписывать в него либо "Да" либо "Нет" - согласно наличию товара на двух складах. Далее свойство используется в умном фильтре при выводе каталога.

Скрипт обновления свойства инфоблока

Для начала напишем скрипт, который будет обновлять значение свойства. Получаем ID элементов нужного инфоблока и, зная этот ID, получаем остаток товара на складах с ID 6 и 13. Если остатки есть, у элемента обновляется свойство "В наличии" на значение "Да". Если остатков нет, свойство обновляется на "Нет".

use Bitrix\Main\Loader;

Loader::includeModule('iblock');

$dbGoods = CIBlockElement::GetList(
    false,
    array(
        'IBLOCK_ID' => '4', // ID инфоблока
        'ACTIVE' => 'Y' // Только активные
    ),
    false,
    false,
    array(
        'ID'
    )
);
while ($arGood = $dbGoods->Fetch()) {
    $hasOnStore = 0; // Счетчик наличия
    $storeRes = CCatalogStoreProduct::GetList(
        false,
        array(
            "PRODUCT_ID" => $arGood['ID'],
            'STORE_ID' => array(6, 13) // ID нужных складов
        ),
        false,
        false,
        array(
            "AMOUNT" // Нужно только количество
        )
    );
    while ($arStoreParam = $storeRes->Fetch()) {
        $hasOnStore += $arStoreParam['AMOUNT'];
    }
    $propertyValue = $hasOnStore > 0 ? 'Да' : 'Нет';

    CIBlockElement::SetPropertyValues(
        $arGood['ID'],
        4, // ID инфоблока
        $propertyValue, // Значение Да или Нет
        'ATT_NAL_FIL' // Код нужного свойства
    );
}

Запускаем этот скрипт в командной php-строке: убеждаемся в его работоспособности и в том, что он отрабатывает быстрее, чем за 10 минут.

Если скрипт отрабатывает долго, лучше не вешать его выполнение на агента и сделать запускаемым напрямую из crontab, средствами сервера. В моем случае, в каталоге более
60 000 товаров, скрипт отрабатывает за 20-30 секунд.

Создание агента в 1С-Битрикс

Для начала добавляем функцию агента в init.php (лучше через include_once отдельным файлом), модуль инфоблоков в нем не подключаем. В моем случае агент будет называться (его функция, точнее) UpdateAvPropAgent.

function UpdateAvPropAgent()
{
    $dbGoods = CIBlockElement::GetList(
        false,
        array(
            'IBLOCK_ID' => '4',
            'ACTIVE' => 'Y'
        ),
        false,
        false,
        array(
            'ID'
        )
    );
    while ($arGoods = $dbGoods->Fetch()) {
        $hasOnStore = 0;
        $storeRes = CCatalogStoreProduct::GetList(
            false,
            array(
                "PRODUCT_ID" => $arGoods['ID'],
                'STORE_ID' => array(6, 13)
            ),
            false,
            false,
            array(
                "AMOUNT"
            )
        );
        while ($arStoreParam = $storeRes->Fetch()) {
            $hasOnStore += $arStoreParam['AMOUNT'];
        }
        $propertyValue = $hasOnStore > 0 ? 'Да' : 'Нет';

        CIBlockElement::SetPropertyValues(
            $arGood['ID'],
            4, // ID инфоблока
            $propertyValue, // Значение Да или Нет
            'ATT_NAL_FIL' // Код нужного свойства
        );
    }
    return 'UpdateAvPropAgent();';
}

Далее идем в админку сайта, по пути "Настройки -> Настройки продукта -> Агенты" и добавляем нового агента:

Создание агента в 1С-Битрикс, на реальном примере
  • Устанавливаем время следующего запуска (можно оставить пустым, но лучше что-то вписать. Поле перезапишется после ближайшего запуска агента).
  • Указываем, что агент использует модуль "iblock".
  • Вписываем функцию агента, так же как назвали ее в init.php: UpdateAvPropAgent(); (обязательно с
    (); на конце).
  • Указываем интервал, с которым агент будет выполняться. На скриншоте каждые 60 секунд но это слишком часто, поставьте раз в час (это 3600 секунд).

Само собой, обязательно переключите выполнение всех агентов на cron, чтобы сайт не тормозил, используя хиты пользователей

Михаил Базаров 11.08.2024
Тоже самое на D7, при тестах работает чуть медленее. Примерно на 10-15 секунд дольше
Код
use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementTable;
use Bitrix\Catalog\StoreProductTable;

function UpdateAvPropAgent()
{
    // Подключение необходимых модулей
    if (!Loader::includeModule('iblock') || !Loader::includeModule('catalog')) {
        return 'UpdateAvPropAgent();'; // Перезапуск агента в случае ошибки подключения модулей
    }

    // Получение списка активных элементов из инфоблока
    $elements = ElementTable::getList([
        'filter' => [
               'IBLOCK_ID' => 4, 
               'ACTIVE' => 'Y'
         ],
        'select' => ['ID']
    ]);

    while ($element = $elements->fetch()) {
        $hasOnStore = 0;

        // Проверка наличия остатков на определенных складах
        $storeProducts = StoreProductTable::getList([
            'filter' => [
                   'PRODUCT_ID' => $element['ID'], 
                   'STORE_ID' => [6, 13]
             ],
            'select' => ['AMOUNT']
        ]);

        while ($storeProduct = $storeProducts->fetch()) {
            $hasOnStore += $storeProduct['AMOUNT'];
        }

        // Установка значения свойства в зависимости от наличия остатков
        $propertyValue = $hasOnStore > 0 ? 'Да' : 'Нет';
        \CIBlockElement::SetPropertyValuesEx(
            $element['ID'], 
            4, 
            ['ATT_NAL_FIL' => $propertyValue]);
    }

    return 'UpdateAvPropAgent();'; // Перезапуск агента
}

Блог-note: заметки разработчика

Установка поиска Sphinx на Ubuntu 22.04 для 1С-Битрикс

Задача: установить и сконфигурировать поиск Sphinx под управлением Ubuntu 22.04 и панели управления HestiaCP для использ...

Скопировать номер телефона из поля пользователя в телефон для регистрации

Задача, на конкретном сайте: раньше все пользователи регистрировались по стандартному режиму, через логин(e-mail) и паро...

Не дать пользователю купить больше одного товара, в Битрикс

Иногда нужно и такое: Например: на одном из разрабатываемых сайтов, мне нужно было создать всего 4 товара. при этом поку...

Отсортировать предложения по цене в каталоге 1С-Битрикс

Задача: в 1С-Битрикс есть настройка для вывода предложений по стоимости, но она не функционирует должным образом. Необхо...

Старые шаблоны битрикс для простой верстки

Новые версии типового интернет-магазина, который идет в комплекте с Битрикс (от 12 версии и выше), достаточно технологич...

Time Capsule на Windows 10. Хранение бекапов Time Machine на компьютере с Windows 10

Заметку написал скорее для себя, что бы собрать все в одну кучу. Написана на базе нескольких разрозненных, по интернету,...

Вывести все товары, с постраничной навигацией, из всех разделов инфоблока

По сути, эта заметка, небольшой лайфхак. Достаточно часто нужно, в корне каталога, в ТОП-е товаров вывести все товары вс...

Дополнительные параметры в меню Битрикс

Иногда нужно присвоить какой-то функционал к конкретному пункту меню в битрикс. Например открывать ссылку в новом окне и...

Автоматическое создание подразделов в инфоблоке при добавлении раздела: реализация события OnAfterIBlockSectionAdd

Задача: когда контент-менеджер создает раздел в инфоблоке, необходимо автоматически создавать подразделы с заранее задан...