Upsert custom fields bei Update Methode - Werte/Values sollen bestehen bleiben

Moinsen,

ich habe eine Frage bzgl. der custom fields / Attribute.
Wir haben in einem Plugin einige Custom Fields, welche nun durch ein Update des Plugins erweitert werden sollen.

BEISPIEL:

$this->productRepository->upsert([[
'id' => '0a1b1ab305a94debb53d5aedf5349b8c',
'customFields' => ['swag_example_size' => 15, 'swag_example_color' => '#189eff']
]], $context);

Vor dem Hintergrund, dass wir eindeutige ids und upsert verwenden habe ich folgende Frage:

FRAGE:
Wenn wir in der Plugin Update-Methode einfach die kompletten custom fields per upsert-Methode aktualisieren und neue Felder hinzufügen, bleiben die vom Kunden hinterlegten Werte bestehen?

Wir führen keine weiteren Checks durch, sondern verlassen uns rein auf die ID und die upsert-Methode.
Wir haben das bisher in der Entwicklungsumgebung getestet, haben aber Angst, etwas zu übersehen.

Jemand Erfahrung damit? Vielen Dank!

1 „Gefällt mir“

Frage mich gerade das gleiche, weil ich mit update() gerade den bestehenden Inhalt verloren habe. Funktioniert das mit upsert()?

Edit: auch mit upsert() scheint es gerade alles rausgeschmissen zu haben. Oder merged es nur auf der obersten Ebene?

Wenn du ein update/upsert auf customFields durchführst, dann überschreibst du immer alles

Stimmt scheinbar.

Hab aber gerade auf dem Entity die \Shopware\Core\Framework\DataAbstractionLayer\EntityCustomFieldsTrait::changeCustomFields() Methode gefunden, die bestehende Einträge beibehält. Das läuft aber nicht rekursiv, gilt also nur für die oberste Ebene.

Allows to change custom fields.
If you pass only one field name, the value of the field will be changed. If you pass multiple field names, an array with the field names as keys and the values as values will be changed.

Upsert beteutet ja nur, das der Artikel neu angelegt wird, falls er nicht existiert.

function upsert(entity){
    if (entity.id){
        update(entity)
    }else{
        insert(entity)
    }
}

Es wird also immer überschrieben, weil du den Artikel ganz normal aktualisiert (ist immer ein update, denn id ist ja immer vorhanden). Wäre ja auch schlecht, wenn da Werte einfach ignoriert würden. Entweder du liest den Wert vorher aus und übergibst ihn mit oder du übergibst gleich nur die neuen Custom-Felder, dann werden die alten auch nicht überschrieben.

Aber du kannst das in der update()-Methode des Plugins gleich über Sql ändern wie du es brauchst:

UPDATE product_translation
SET `custom_fields` = JSON_MERGE_PATCH(
    '{"swag_example_size":  15, "swag_example_color": "#189eff"}'
    `custom_fields`, 
)

Über JSON_MERGE_PATCH wird custom_fields auf einen Default-Wert gesetzt und mit den bestehenden Werten gemerget/überschrieben.

Den Artikeln danach einen speziellen Wert zuzuweisen, sollte dann ja über einen Artikel-Import Prozess stattfinden und nicht über eine Plugin-Aktualisierung.

Ist insgesamt performanter und vom Ablauf auch irgendwie logischer.