# Shopware 6

Bei der Wahl von Shopware 6 als Backend Shopsystem, verwendet hubble nicht die hubble Data API, sondern die REST API Endpoints, die Shopware für verschiedene Entitäten bereitstellt. Zum einen ist dies die Sales Channel API (opens new window), die verschiedene Funktionalitäten für den Warenkorb, den Kunden, Produkte und sogar die Authentifikation bereitstellt und zum anderen ist dies die neue Store API (opens new window). Für die Authentifikation in Shopware wird ein sw-access-key benötigt. Im Folgenden ist ein klassischer Ablauf zum Erhalt und Verwendung dieses Keys dargestellt:

# Shopware als Backend: sw-context-token und sw-access-key

Durch das Hinzufügen von Produkten zum Warenkorb wird durch die ProductDetailAddToCart Komponente bei der ersten Interaktion eine action im zugehörigen Vuex Store Modul sw/modCart aufgerufen, mit der Aufgabe einen sw-context-token (opens new window) zu erhalten. Da dieser Token in subsequenten Interaktionen mit der API benötigt wird, wird dieser im darauf folgenden Schritt lokal im Vuex Store und zusätzlich als Cookie im Browser abgespeichert.

Die Voraussetzung, um einen sw-context-token von der API zu erhalten, ist das Setzen des Auth Tokens im Request. Dieser Auth Token ist im Admin Panel erreichbar und muss in die ~/.env Datei des Projektes eingetragen werden. Mehr Informationen zum Umgang mit den in der ~/.env eingetragenen Werte gibt es im Abschnitt Konfiguration.

  • Schritt 1: Eintrag des Auth Keys in die ~/.env
// ~/.env
API_SW_ACCESS_KEY = <KEY-FROM-ADMIN-AREA>
1
2

WARNING

Client-seitig erlaubte Keys müssen in der ~/nuxt.config.js auf die Whitelist gesetzt werden, damit diese zur Verfügung stehen. Zur korrekten Einrichtung sollte der Abschnitt Konfiguration referenziert werden.

  • Schritt 2 : Zur Verwendung des Keys wird process.env referenziert
// ~/modules/@hubblecommerce/hubble/core/store/modApi.js
let authToken = process.env.API_SW_ACCESS_KEY
1
2

Dies bedeutet, dass im Falle von Shopware der sw-context-token kennzeichnendes Merkmal der Session ist. Dadurch wird ermöglicht, dass Shopbesucher Produkte dem Warenkorb beliebig hinzufügen und entfernen können, sowie die gewünschte Menge anpassen können, ohne sich dabei anmelden oder registrieren zu müssen.

TIP

Die Reihenfolge der Zustandsspeicherung nach Veränderung des States folgt immer demselben Schema: Ein Request an einen API Endpunkt wird über die action modApi/apiCall gemacht, welche den API Access Key aus der ~/.env und den sw-context-token benötigt. Die Response dazu wird im lokalen Vuex Store mit Hilfe des Moduls sw/modCart gespeichert und anschließend im Browser als Cookie und per $localForage gespeichert. Der Aufruf der action sw/modCart/saveCartToStorage folgt immer auf jenen API Request, der aufgrund einer Interaktion mit dem Warenkorb ausgelöst wurde.

Für Details zu verwendeten Modulen, im Zusammenhang mit dem Thema Sessions, kann der Abschnitt Sessions der Dokumentation referenziert werden.

Im Folgenden ist ein klassischer Ablauf zu sehen, bei dem zuerst ein Request an die Shopware API versendet wird und darauffolgend das Response Objekt verwertet wird.

Der Aufruf der action swUpdateLineItem führt zu einem API patch Request an die Shopware Sales Channel API.

// ~/modules/@hubblecommerce/hubble/core/store/sw/modCart.js
updateItem({ commit, state, dispatch }, payload) {
    return new Promise((resolve, reject) => {
        // makes API patch request w/ payload object
        dispatch('swUpdateLineItem', { id: state.productToUpdate, qty: state.qtyToUpdate })
            .then((res) => {
                // updates vuex store state 
                commit('setCartItemsCount', state.cart.items_qty + payload.qty );

                // saves cart to browser storage via localForage
                dispatch('saveCartToStorage', { response: res }) 
            }
        }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ~/modules/@hubblecommerce/hubble/core/store/sw/modCart.js
swUpdateLineItem({commit, state, dispatch, rootState, getters}, payload) {
    const _endpoint = `/sales-channel-api/v1/checkout/cart/line-item/${payload.id}`;

    return new Promise((resolve, reject) => {
        dispatch('apiCall', {
            action: 'patch',
            tokenType: 'sw',
            apiType: 'data',
            swContext: state.swtc,
            endpoint: _endpoint,
            data: {
                quantity: payload.qty
            }
        }, { root: true })
            .then(response => {
                resolve(response);
            })
            .catch(error => {
                console.log("swUpdateLineItem error: ", error);

                reject(error);
            });
        });
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# Darstellung der Shopware Erlebniswelten

Um die Abbildung von Erlebniswelten in der hubble PWA zu verstehen, ist es wichtig, nicht nur die Definition, sondern auch die Terminologie zu kennen, welche Shopware verwendet:

Shopware's Erlebniswelten bieten eine Möglichkeit für Shop Administratoren eigenständig im Admin Bereich, aus bestehenden Komponenten, eine Seite per Drag & Drop zu erstellen. Dabei ist die Kernidee Content Management und eCommerce auf einer Seite jeweils zu vereinen (Erlebniswelten: Content Management in Shopware 6 (opens new window)). Die Art von Komponenten, die sich in den Erlebniswelten Seiten einbinden lassen, werden in Shopware als Blöcke bezeichnet. Diese bieten sogenannte Slots an, um eine Positionierung von sogenannten Elementen zu ermöglichen. Blöcke sind im Admin Bereich gruppiert in beispielweise Text, Image und Text+Image. Dabei können Blöcke vom Typ Text, nur den Element Typen Text in dem entsprechenden Slot darstellen.

Eine weitere Ebene zur Gruppierung bieten sogenannte Sections, die mehrere Blöcke einbinden können. Somit besteht also eine Seite, die mit den Erlebniswelten im Shopware Admin Bereich erstellt wurde, aus mehreren Sections.

Zu diesem Thema existiert eine Einleitung in der Shopware 6 Dokumentation, die unter dem Kapitel Erlebniswelten (opens new window) einsehbar ist.

Die Erlebniswelten zählen zum Entitätstyp Kategorie, wodurch die state.modApiResources.pageType State Variable in hubble den Wert category erhält und somit über die ~/components/productlist/ViewCategory.vue Komponente dargestellt wird. Hier einmal ein stark vereinfachter, für den Fall Shopware - in Bezug auf Erlebniswelten - direkt relevanter, Auszug:






 
 
 
 





// ~/components/productlist/ViewCategory.vue
<template>
    <div class="view-category">
        <template v-if="isShopware">
            <div class="container">
                 <sw-section v-for="cmsSection in cmsSections"
                            :key="cmsSection.id"
                            :content="cmsSection"
                 />
            </div>
        </template>
    <div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13

Wie in den oben markierten Zeilen zu erkennen ist, wird in hubble über die Sections iteriert, die der Erlebniswelt im Admin Bereich hinzugefügt wurden. Die hubble Komponenten zur Darstellung der Erlebniswelten befinden sich im Ordner ~/components/swComponents/section.vue. Zur Abbildung der Blöcke und deren Slotinhalte, existieren die Unterordner /blocks und /slots. Falls es Blöcke oder Elemente geben sollte in Zukunft, für die es keine entsprechende Dateien in hubble gibt, dann gibt es dafür die NoComponent Komponente. Das Mapping der API Response und somit die korrekte Darstellung, geschieht mit Hilfe der ~/components/swComponents/helper.js Datei. Diese enthält einige Helper Funktionen, welche die jeweiligen, aus den Ordnern /blocks und /slots, benötigten Komponenten importiert.

# Beispiel - Die Abbildung des Erlebniswelten Block Typs "Image" in hubble:

Das Template:

// ~/components/swComponents/blocks/image.vue
<template>
    <div>
        <div class="col-12">
            <component :is="getSlot" :content="getContentByPosition(content.slots, 'image')" />
        </div>
    </div>
</template>
1
2
3
4
5
6
7
8

Das Skript:

<script>
  import { blockMixins } from '../helper'

  export default {
      name: 'ImageBlock',

      mixins: [blockMixins],

      props: {
          content: {
              type: Object,
              default: () => ({})
          }
      },

      computed: {
          getSlot() {
              return this.getSlotByPosition(this.content.slots, 'image');
          }
      }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Wie, sowohl in der computed Property, als auch im Template zu erkennen ist, werden die folgenden Helper Funktionen aus der ~/components/swComponents/helper.js verwendet:

// ~/components/swComponents/helper.js
export const blockMixins = {
    methods: {
        getSlotByPosition(slots, position) {
            let typeName = ''
            _.forEach(slots, slot => {
                if (slot.slot === position) {
                    typeName = slot.type
                }
            })
            return returnSlotByType(typeName)
        },
        getContentByPosition(slots, position) {
            let slotContent = {}
            _.forEach(slots, slot => {
                if (slot.slot === position) {
                    slotContent = slot
                }
            })
            return slotContent
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Die getSlotByPosition ist dann letztendlich für das importieren zuständig, sei es des Elements, welches im jeweiligen Slot, in diesem Fall image, angezeigt werden soll oder der Placeholder Komponente ~/components/swComponents/NoComponent.vue, falls es keine entsprechende zu importierende Komponente gibt in hubble.

// ~/components/swComponents/helper.js
function returnSlotByType(type) {
    return () =>
        import('./slots/' + type).catch(() => {
            return import('./NoComponent')
        });
}
1
2
3
4
5
6
7

Zusammenfassend lässt sich somit also sagen, dass hubble die Basis für die Einbindung von neuen Custom Erlebniswelt Blöcken und Elementen bereitstellt. Es gilt nur die entsprechenden Komponenten in den Ordnern /blocks und /slots, unter der Verwendung der Helper Funktionen in der ~/components/swComponents/helper.js, nach demselben Muster zu erstellen. Für die Erstellung von Custom Komponenten, die im Adminbereich des Shopware Erlebniswelten Editors zur Verfügung stehen sollen, können dabei die folgenden Kapitel der Shopware Entwicklerdokumentation referenziert werden:

Für Möglichkeiten zur Individualisierung existierender Erlebniswelt Komponenten in hubble kann der Abschnitt Abbildung der Erlebniswelten in hubble in der How To Section dieser Dokumentation referenziert werden.