R
R
ragnar_ok2019-10-14 09:50:40
1C-Bitrix
ragnar_ok, 2019-10-14 09:50:40

How to update infoblock elements (REST)?

Every 24 hours I update the elements of the infoblock. I receive data from the endpoint API (REST).
Designed adding new elements and updating the existing one in this way:

  1. I receive json objects from the endpoint API and save the checksum (crc32) of each object into a variable;
  2. I receive the getList();elements of the infoblock by the method. In the field XML_ID I store external ID. I store the checksum in the TMP_ID field;
  3. if the TMP_ID of the existing element is equal to the checksum of the outer element, then I check the following condition. If the XML_ID of the infoblock element is equal to the ID of the external element, then I add it to the 'UPDATE' array. Otherwise, I add it to the 'ADD' array;
  4. I add or update elements depending on what array they are in.

How rational is my approach? I'm not sure about my decision. If everything is fine, then please give the appropriate answer too.
Below is a stripped-down code in procedural style:
$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);
    }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexander, 2019-10-14
@ragnar_ok

0 Why not md5?
1 Kinda weird - do you check the checksum and update the element if it matches? What for? If you have a data control and they have not changed - why update? Skip this item.
2 Why check the checksums first? What's the point if it will be different for the majority?
3 You understand that your algorithm (if you described it correctly - I didn’t look at the code) will update elements that do not need to be updated (with the same hash) and will create duplicate objects if they need to be updated, since you add elements with different hashes to the ADD array?
As I would do - get the objects.
I collected their external ids and extracted from the database a reference book for these ids using the XML_ID field, such as where XML_ID => TMP_ID.
Then I would go through the input objects, calculating a hash for them, and if an object with XML_ID == id is in the directory, then I would check the hash. If it matches, we skip the object. If not, add it to updatedate. If the object is not in the directory, add it to add.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question