Entity extension in der Administration

Hallo zusammen,

ich habe mir die Entity-Extensions angeschaut und insbesondere den entsprechenden Guide nachgespielt, allerdings als Extension zu LandingPage, nicht Product: https://developer.shopware.com/docs/guides/plugins/plugins/framework/data-handling/add-complex-data-to-existing-entities

Klappt auch alles soweit. Jetzt möchte ich testhalber im Admin (als Beispiel habe ich mir die LandingPage-Entität ausgesucht) das String-Field „custom_string“ meiner Example-Extension in einem zusätzlichen Tab darstellen. (Mir ist klar, für ein einfaches String-Field könnte ich custom fields verwenden, ich möchte das wie gesagt nur ausprobieren.)

Ich habe mir zudem das Bundle-Example angeschaut und dort auch das Überschreiben der Criteria gesehen, um die (One-To-One-)Association (siehe Guide oben) hinzuzufügen - auch das ergibt Sinn und ist klar soweit.

Zwei Fragen:

  • Wie bekomme ich meine Extension nun in das LandingPage-Objekt. Unter „extensions“ ist nichts zu finden. Der api/search/landingPage-request bekommt die landing-page und im include ist auch meine Example-Extension mit data = null.
  • Bei dem OneToOneAssociationField meiner Extension habe ich autoload = true gesetzt. Ist dann das Hinzufügen der Association zur Criteria überhaupt noch notwendig?

Kurz, mir ist nicht ganz klar, wie ich nun in einem zusätzlichen Beispiel-Tab der LandingPage (der wird angezeigt) eine sw-component über v-model an meinen custom_string der Extension binde.

Danke für die Hilfe
Manuel

Ok, bin jetzt weiter.

Erstmal zur 2. Frage: Hat sich erledigt, natürlich muss ich entweder autoload=true angeben, dann ist die Association immer da, oder ich erweitere das Criteria-Objekt.

Zu 1: Mein Problem war eigentlich nur, dass anfangs noch kein Record da ist (natürlich). Also habe ich testweise in view/example-extension-vew/index.js folgendes fabriziert (schön ist was anderes :)):

Component.register('example-extension-view', {
    template,

    inject: ['repositoryFactory'],

    computed: {
        landingPage() {
            let landingPage = Shopware.State.get('swCategoryDetail').landingPage;
            if (!landingPage.extensions.exampleExtension) {
                landingPage.extensions['exampleExtension'] = this.exampleExtensionRepository.create();
            }

            return landingPage;
        },

        exampleExtensionRepository() {
            return this.repositoryFactory.create('example_extension');
        },
    },
});

Damit klappt es auch, weil ich nun eine entsprechende Entity in landingPages.extensions.exampleExtension habe, falls (noch) keine da ist.

Meine Frage ist nun: muss man das selbst handeln oder bekommt man den Core dazu, die Extension-Entity von selbst reinzupacken?

Falls das hier jemand liest: Besser ist es, die Reaktivität nicht aufzugeben, also:

this.$set(landingPage.extensions, 'exampleExtension', this.exampleExtensionRepository.create(Context.api));

Die Frage, wie sich das hübscher lösen lässt, bleibt. :slight_smile:

1 Like

Ich lese mit, danke dir für die Infos!
Habe das gleiche vor und komme auch an vielen Stellen nicht weiter.

In den ganzen Core Dateien ist das Vorgehen analog. Glaube nicht, dass man das selbst gepackt bekommt.

Wo bist du den auf $set gestoßen? Habe das bisher fast noch nie gesehen.

Selbst abgeändert. ich hatte (wie im ersten Listing abgebildet) zuerst einfach die Prop meiner Beispielextension an landingPage.extension drangekleistert, falls die Prop nicht vorhanden ist. Im Kontext eines Vuex-Stores ist das natürlich unsauber, weil die Reaktivität flöten geht. Bei dem Beispieltextfeld meiner Extension fällt das nicht weiter auf, aber Components, die auf State-Changes reagieren sollen, würden dann natürlich nicht mehr reagieren. Daher habe ich Vue.set verwendet, um die Prop dem Objekt hinzuzufügen und die Reaktivität somit sichergestellt (sind ja Proxies, AFAIR). Ich hoffe, das war jetzt einigermaßen verständlich. :slight_smile:

Man könnte wahrscheinlich auf den Käse verzichten, indem man das Tab erst nach einem ersten Speichern der Entität (also LandingPage in meinem Fall) anzeigt (v-if). Aber ich wollte eben schauen, wie ich es hinbekomme, dass es sofort da ist.

Ich bin mit meiner Implementierung weitegekommen und beschreibe die Schritte kurz:

Meine Extension geht auf die product-Table und fügt einen Gültigkeitszeitraum für das Produkt hinzu (1:1 Verknüpfung zwischen meiner Extension und der product-Table).

Im Adminbereich habe ich dafür dieses Feld mit v-Model gebunden

<sw-datepicker
    v-model="product.extensions.myExtension.validTo"
    date-type="datetime-local"
    :label="$tc('myExtension.product.detailBase.labelValidTo')"
/>

Das klappt auch wunderbar. Problem ist nur, wenn es noch keinen Datensatz in meiner Extensions-Tabelle gibt. Dann steigt vue leider aus und zeigt gar nichts mehr auf der Produktseite an. Ich habe versucht hier eine Lösung zu basteln, ist mir aber nicht gelungen. Daher stelle ich nun einfach sicher, dass es immer einen passenden Datensatz in meiner Extensions-Tabelle gibt (beim Erstellen der Tabelle über ein Insert aller Datensätze und beim Hinzufügen von neuen Produkten über einen Trigger).
Sicherlich nicht die sauberste Lösung, weil nun auch für die Produkte Datensätze angelegt werden, für die gar kein Gültigkeitszeitraum existiert - aber so funktioniert es mit nur sehr, sehr wenig Aufwand im Dashboard.