ragnar_ok
@ragnar_ok

Как актуализировать элементы инфоблока (REST)?

Каждые 24 часа обновляю элементы инфоблока. Данные получаю от API эндпоинта (REST).
Разработал добавление новых элементов и обновление существующий таким образом:
  1. получаю от API эндпоинта json-объекты и сохраняю в переменную контрольную сумму (crc32) каждого объекта;
  2. получаю методом getList(); элементы инфоблока. В поле XML_ID храню внешний ID. В поле TMP_ID храню контрольную сумму;
  3. если TMP_ID существующего элемента равен контрольной сумме внешнего элемента, то проверяю следующее условие. Если XML_ID элемента инфоблока равен ID внешнего элемента, то складываю в массив 'UPDATE'. В обратном случае складываю в массив 'ADD';
  4. Добавляю или обновляю элементы в зависимости от того, в каком массиве они находятся.

Насколько рационален мой подход? Я не уверен в своем решении. Если все нормально, то дайте, пожалуйста, тоже соответствующий ответ.
Ниже привожу урезанный код в процедурном стиле:
$itemArray = [
    'items' =>
    [
        'id' => 1,
        'name' => 'name'
    ]
]; // массив с объектами полученными от API

$idArray = []; // массив с существующими элементами инфоблока
$resultObj = ElementTable::getList([
    'select' => ['ID', 'XML_ID', 'TMP_ID'],
    'filter' => ['IBLOCK_ID' => 1, 'XML_ID' => array_column($itemArray, 'id')]
]);
while ($resultArray = $resultObj->fetch()) {
    $idArray[$resultArray['XML_ID']] = $resultArray;
}

$i = 0;
foreach ($itemArray['items'] as $item) {
    $crc32 = hash('crc32', serialize($item));
    // сохраняю в переменную контрольную сумму каждого объекта
    if ($idArray[$item['id']]['TMP_ID'] === $crc32)
        continue;


    $type = array_key_exists($item['id'], $idArray) ? 'UPDATE' : 'ADD';
    $index = $idArray[$item['id']]['ID'] ?? $i++;


    $outputArray[$type][$index] = [
        'IBLOCK_ID' => $ID,
        'NAME' => $name,
        'XML_ID' => $item['id'], // сохраняю внешний ID
        'TMP_ID' => $crc32 // сохраняю контрольную сумму
    ];
}

$el = new CIBlockElement;

if (count($outputArray['ADD']) > 0) {
    foreach ($outputArray as $output) {
        $resultArray = $el->Add($output, false, false);
    }
}

if (count($outputArray['UPDATE']) > 0) {
    foreach ($outputArray as $id => $output) {
        $resultArray = $el->update($id, $output, false, false);
    }
}
  • Вопрос задан
  • 346 просмотров
Решения вопроса 1
0 А чо не md5?
1 Как-то странно - вы проверяете контрольную сумму и обновляете элемент если она совпадает? А зачем? Если у вас контролька от данных и они не изменились - зачем обновлять? Пропустите этот элемент.
2 Зачем вообще сначала сверять контрольные суммы? Какой в этом смысл если у большинства он будет разный?
3 Вы понимаете что ваш алгоритм (если вы его правильно описали - я код не смотрел) будет обновлять элементы которы не нуждаются в обновлении (с совпадающем хэшем) и будет создавать дубли объектов, если их надо обновить, так как вы добавляете элементы с отличными хэшами в массив ADD?

Как делал бы я - получил объекты.
Собрал их внешние id и извлек из базы справочник по этим id по полю XML_ID, такой где XML_ID => TMP_ID.
Далее переберал бы входные объекты, вычисляя для них хэш и если объект с XML_ID == id есть в справочнике, то сверял бы хэш. Если он совпадает - пропускаем объект. Если нет - добавляем его в uppdate. Если объекта нет в справочнике - добавляем его в add.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы