CustomFields für existierende Entity erstellen

Hallo,

ich versuche einer existierenden Entity programmatisch CustomFields zuzuweisen. Ich habe schon herausgefunden, wie ich der Entity beim Speichern das customFields-Objekt mitgebe. Nun muss ich noch die Felddefinitionen erstellen, damit diese beim Speichern auch wirkllich zu Verfügung stehen und die Daten nicht ins Leere laufen. Das habe ich in der Doku dazu gefunden: https://docs.shopware.com/en/shopware-platform-dev-en/internals/core/data-abstraction-layer/custom-field

$customFieldSetRepository->create([[
    'name' => 'swag_backback',
    'customFields' => [
        ['name' => 'swag_backpack_size', 'type' => CustomFieldTypes::INT],
        ['name' => 'swag_backpack_color', 'type' => CustomFieldTypes::TEXT]
    ]
]], $context);

Weiß jemand, wo man das Snippet einbindet? Bzw. brauche ich nicht unbedingt ein Set, da die Felder nicht über den Admin pflegbar sein müssen:

Custom field sets are optional. If your custom fields should not be editable in the administration, it’s possible to add custom fields without an custom field set association (customFieldSet = null). The name still needs to be globally unique.

Ich finde aber nicht heraus, wie ich die benötigten Felder erstellen kann…

Das habe ich mich auch schon gefragt. Was zumindest funktioniert, wäre das Hinzufügen deines Codes innerhalb der install() methode deines Moduls (https://docs.shopware.com/en/shopware-platform-dev-en/internals/plugins/plugin-base-class?category=shopware-platform-dev-en/internals/plugins#install):

$customFieldSetRepository = $this->container->get('custom_field_set.repository');
$customFieldSetRepository->create([[
    'name' => 'swag_backback',
    'customFields' => [
        ['name' => 'swag_backpack_size', 'type' => CustomFieldTypes::INT],
        ['name' => 'swag_backpack_color', 'type' => CustomFieldTypes::TEXT]
    ]
]], $context);

Ich bin allerdings selbst unsicher, ob das Hinzufügen des Skriptes an dieser Stelle im Sinne des Erfinders ist.

Eine offizielle Antwort wäre hier nicht schlecht.

1 Like

Ah super, das wäre ja schon mal ein Ansatz, danke dir! Analog dazu wäre der Code zum Zuweisen einer Entity dann so?

$productRepository = $this->container->get('product.repository');

$productRepository->upsert([[
    'id' => $id,
    'customFields' => ['swag_backpack_size' => 15, 'swag_backpack_color' => 'blue']
]], $context);

Ich frage mich wo man in der Doku die erste Zeile von dir findet oder ist hier Symfony Vorwissen gefragt? Außerdem frage ich mich auf was sich die $context Variable Bezieht. Weißt du da was? Danke!

 

Edit 17.03.20:

$context wir hier erklärt: https://docs.shopware.com/en/shopware-platform-dev-en/internals/core/context

Ein system default context lässt sich folgendermaßen erstellen:

use Shopware\Core\Framework\Context;

$context = Context::createDefaultContext();

Wenn ich es selbst ausprobiert habe, ergänze ich meine Ergebnisse.

Hi,

die erste Zeile hat sich mir nach dem Vorbild der offiziellen PayPal Extension erschlossen: https://github.com/shopwareLabs/SwagPayPal/blob/master/src/SwagPayPal.php#L66

$context kommt in der install methode als Übergabeparameter mit, den musst du (in diesem Fall) nicht selbst erstellen.

Dein Code zum Zuweisen der Werte zum Entity sieht mir korrekt aus, wobei die Verwendung von $this->container->get(‚irgendein-service‘), nicht zwangsweise (und das hängt davon ab, wo du den Service verwendest) Best Practice ist. In der Installationsdatei hast du wohl keine andere Wahl, wenn du aber z.B. in einem anderen/eigenen Service unterwegs bist, kannst du das Produkt Repository via Dependency Injection (d.h. Eintragungen in der src/Resources/config/services.xml deines Moduls) hinzufügen.

Wenn du das Product Repository einem eigenen Service hinzufügst sieht das dann in besagter services.xml in etwa so aus:

Das Repository Object kommt dann im constructor deines Services mit.

Siehe dazu auch: https://developers.shopware.com/developers-guide/services/

Danke dir! Das verschafft mir auf jeden Fall mal mehr Durchblick. Hast du das alles aus der Shopware Doku oder hast du bereits Erfahrung mit Symfony?

Was mir leider immer noch nicht ganz klar ist, ist wie ich nun diese Felder einer Entity zuweise. Mit dem Code oben kann ich ja nur einen Eintrag mit $id x im product.repository ansprechen. Mein Ziel ist es aber der Entity an sich, also für jeder Instantz/jedem Eintrag diese Platzhalterfelder anzulegen, damit ich diese dann in Vue befüllen kann. In Vue kann ich bereits beim Speichern das customFields-Objekt mitgeben, aber da die Felder im DAL nicht registriert sind, wird das Objekt nicht gespeichert. Weißt du da noch was? Danke!

Das meiste habe ich tatsächlich der Shopware Doku entnommen. Symfony Kenntnisse habe ich kaum. Ich komme eigentlich aus der Magento Schiene, dort funktionieren ein paar Grundkonzepte sehr ähnlich, nur ungefähr 3x komplizierter. Unabhängig davon, muss man auch bei Shopware in den Code schauen, wenn man herausfinden will, wie Dinge tatsächlich funktionieren.

Was deine Frage angeht, bin ich nicht sicher, ob ich dich korrekt verstanden habe. Ich antworte mal in der Annahme, dass du die Felder eben in dem jeweiligen Artikel in der Adminoberfläche pflegen willst.

Dafür reicht es, soweit ich das bis jetzt beobachten konnte, wenn du ein Custom Field Set erstellst (welchem logischerweise deine Customfields zugeordnet sind) und dieses Custom Field Set mit dem Artikel Datentyp verknüpfst.

Damit hast du automatisch bereits eine Anzeige deines Custom Field Sets mit den entsprechenden Customfields, welches du bei den Artikeln pflegen kannst.
Somit musst du auch selbst gar nichts mehr in Vue anpassen.

Also angenommen du erstellst dein Custom Field Set und deine Custom Fields wie folgt:

$customFieldSetRepository = $this->container->get('custom_field_set.repository');
$customFieldSetRepository->create(
    [
        [
            'name' => 'swag_backback',
            'config' => [
                'label' => [
                    'en-GB' => 'Custom Fieldset',
                    'de-DE' => 'Custom Fieldset'
                ]
            ],
            'customFields' => [
                [
                    'name' => 'swag_backpack_size',
                    'type' => CustomFieldTypes::INT,
                    'config' => [
                        'componentName' => 'sw-field',
                        'customFieldType' => 'text',
                        'label' => [
                            'en-GB' => 'Swag Backpack Size',
                            'de-DE' => 'Swag Backpack Size',
                        ]
                    ],
                    'active' => true
                ],
                [
                    'name' => 'swag_backpack_color',
                    'type' => CustomFieldTypes::TEXT,
                    'config' => [
                        'componentName' => 'sw-field',
                        'customFieldType' => 'text',
                        'label' => [
                            'en-GB' => 'Swag Backpack Color',
                            'de-DE' => 'Swag Backpack Color',
                        ]
                    ],
                    'active' => true
                ],
            ],
            'relations' => [
                [
                    'entityName' => 'product'
                ]
            ]
        ]
    ], $context->getContext()
);

Dann solltest du, wenn alles gut geht, im Adminbereich bei der Detailansicht eines Artikels im Reiter „Allgemein“, wenn du entsprechend runterscrollst, den Bereich „Zusatzfelder“ mit deinen eigenen CustomFields finden. Sollte ungefähr so aussehen:

Ich hab das jetzt nicht selbst geprüft, aber in ähnlicher Form habe ich das bereits auf diese Weise umgesetzt.
Vielleicht musst du daher noch ein wenig an der Definition des Custom Fieldsets und Customfields feilen.

Eine gute Referenz um nachzuvollziehen, wie Custom Fields und Field Sets und mit welchen Optionen erstellt werden können, sind die Generatoren der Demodaten.
Wenn man sich z.B. https://github.com/shopware/platform/blob/master/src/Core/Framework/Demodata/Generator/CustomFieldGenerator.php sowie die dadurch erzeugten Datensätze dann in der Datenbank ansieht, bekommt man schon eine sehr gute Idee davon, wie der Code für die eigenen Custom Fields aussehen muss.

Hallo.

 

Wisst ihr, wie ich übersetzte Custom Field Values upserte?

        $data => [
            'id' => 'abc123...',
            'productNumber' => '123465',
            ...
            'customFields' => [
                'custom_lorem' => 'ipsum',
                'custom_shortname' => [
                    'de-DE' => 'd',
                    'en-GB' => 'e'
                ],
            ],
        ];

wirft den Fehler  [/1/translations/id…/customFields/custom_shortname] This value should be of type string. Als Array mag es das wohl nicht. custom_lorem geht problemlos.

Danke!