SW 5.2 - Backend Plugin / eigene Attribute in Artikeldetails

Hallo Oliver,

danke für die Auf- und Erklärung.

Das heisst also, wenn man beispielsweise ein eigenes Fieldset hatte, wo beispielsweise 10 TinyMCE-Felder (als Tabs) enthalten waren, sollte man nun am besten alle 10 TinyMCE-Felder unten bei dem Freitextfeld-Fieldset integrieren, damit man die Shopware-Richtlinien einhält und am besten auch zukunftssicher entwickelt? Das schafft natürlich für den Onlineshop-Betreuer etwas weniger Übersicht, da man ein Plugin beziehungsweise dessen zusätzliche Felder nicht direkt “hervorheben kann” und somit nicht direkt erkennt, welches zusätzlichen Felder zu welchem Plugin gehören. Wenn dies aber so gewünscht und gewollt ist, kann ich damit leben - da man zumindestens den Kunden bzw. die Käufer darauf verweisen kann, dass das so von Shopware selbst so gewollt ist. Wenn man es so nimmt, ist und war es ja beispielsweise bei den Varianten immer schon so. Das ganze in einem “in sich geschlossen Fieldset” zu belassen hat aber natürlich auch die neuen Vorteile, die man auch nicht außer acht lassen kann.

Beste Grüße

Sebastian

Hi,

du kannst ja in dem Fieldset ein weiteres „Fieldset/Container/Panel/…“  hinzufügen mit ein wenig Abstand nach oben so dass ersichtlich wird, dass diese Felder zusammen gehören. Durch die Möglichkeit selbst „ExtJS-Types“ definieren zu können, bist du in der Implementierung „fast“ nicht eingeschränkt. Du könntest auch ein Modal-Fenster öffnen in dem die Felder dargestellt werden und beim Schließen des Fensters kannst du die Werte entweder in Hidden-Felder schreiben oder aber einfach in interne Variablen speichern und in der „getValue“ funktion des Feldes wieder auslesen damit diese beim Speichern mit gesendet werden. Da sind der Fantasy keine Grenzen gesetzt ;).

Ihr könnt auch die Positionierung des Attribute Forms in den entsprechenden Module komplett umstellen und z.B. nach oben ziehen.

@Oliver Skroblin schrieb:

Hi,

du kannst ja in dem Fieldset ein weiteres “Fieldset/Container/Panel/…”  hinzufügen mit ein wenig Abstand nach oben so dass ersichtlich wird dass diese Felder zusammen gehören. Durch die Möglichkeit selbst “ExtJS-Types” definieren zu können bist du in der Implementierung fast nicht eingeschränkt. Du könntest auch ein Modal-Fenster öffnen in dem die Sachen dann dargestllt werden und anschließend in Hidden-Felder oder interne Properties zurück schreiben, da sind der Fantasy keine grenzen gesetzt. Ihr könnt auch die Positionierung des Attribute Forms in den entsprechenden Module komplett umstellen und z.B. nach oben ziehen.

Hallo Oliver,

schön zu hören - hier wäre eventuell ein kleines Beispiel-Plugin auch sehr nett, wo man einmal ein eigenes Fieldset beim “Freitext-Fieldset” und in diesem eigene Felder hat. Es geht hier ja schließlich um sehr viele Anpassungen bei so gut wie jedem Shopware Fremdanbieter-Plugin, also auch “ein Haufen Arbeit” für alle, die in Ihrem Plugin ein- oder mehrere Zusatzfelder integriert haben.

Zum Beispiel-Plugin hätte ich noch eine kurze Frage: kann man bei seinem Plugin auch weiterhin von " extends Shopware_Components_Plugin_Bootstrap" ableiten oder muss man von " extends Plugin", damit man Zugriff auf den Attribute-Service hat [@Oliver Skroblin](http://forum.shopware.com/profile/1871/Oliver Skroblin “Oliver Skroblin”)‍ ? Muss man hier wirklich nur update nutzen oder wie vom TE erwähnt auch create, was ja auch laut der Doku so sein müsste oder?

Beste Grüße

Sebastian

 

Wie kann ich ein Attribute ausserhalb des Freitext-Fieldsets darstellen:

Dies müsst ihr individuell lösen, da das Fieldset (Shopware.attribute.Form) in sich geschlossen ist. 

Auch von mir Danke für die Erklärung. Aber ich denke das solltet ihr so noch einmal überdenken. Hier sollte es definitv einen einheitlichen Weg geben!  

Hier ein kleines Beispiel wie Ihr euch ein eigenes Fieldset darin anlegt. Habe nur den SwagAttribute.FieldHandler dafür angepasst der Rest vom Beipiel Plugin ist gleich geblieben.

 

Ext.define('SwagAttribute.FieldHandler', {

    extend: 'Shopware.attribute.FieldHandlerInterface',

    /**
     * @override
     * @param { Shopware.model.AttributeConfig } attribute
     * @returns { boolean }
     */
    supports: function(attribute) {
        var name = attribute.get('columnName');

        if (attribute.get('tableName') !== 's_articles_attributes') {
            return false;
        }

        return (name == 'my_own_validation' || name == 'my_own_type');
    },

    /**
     * @override
     * @param { Object } field
     * @param { Shopware.model.AttributeConfig } attribute
     * @returns { object }
     */
    create: function(field, attribute) {
        var name = attribute.get('columnName'),
            returnValue = null;

        if (!this.myFieldSet) {
            this.myFieldSet = this.createFieldSet();
            returnValue = this.myFieldSet;
        }

        switch (name) {
            case 'my_own_type':
                this.myFieldSet.add(this.createOwnTypeField(field));
                break;
            case 'my_own_validation':
                this.myFieldSet.add(this.createOwnValidationField(field));
                break;
        }

        return returnValue;
    },

    createFieldSet: function() {
        return Ext.create('Ext.form.FieldSet', {
            margin: '30 0 0',
            title: 'My seo configuration or something else',
            items: [
                Shopware.Notification.createBlockMessage('Some notice for the customer', 'notice')
            ],
            layout: 'anchor',
            defaults: {
                anchor: '100%'
            }
        });
    },

    createOwnTypeField: function(field) {
        return Ext.apply(field, {
            xtype: 'swag-attribute-type'
        });
    },

    createOwnValidationField: function(field) {
        return Ext.apply(field, {
            xtype: 'textfield',
            emptyText: 'My default value',
            validateOnBlur: true,
            validate: function() {
                //validate some stuff
                return true;
            }
        });
    }
});

Kann dann so aussehen:

2 Likes

Und es wird also auch möglich sein eigene Attribute anzulegen, den neuen Konventionen zu Folge, die aber für den Kunden nicht ersichtlich sind und auch nicht bearbeitet werden können? Ich denke da an reine Konfigurationfelder, die Fremdschlüssel enthalten etc. Dann wäre die Lösung mit eigenem Fieldset unter den Freitextfeldern ein Kompromiss mit dem ich leben könnte.

Abgesehen davon sehe ich, wie viele hier, das Problem, dass insbesondere Shops mit vielen individuellen Entwicklungen ein Update mit Blick auf weitere Kosten scheuen werden. Das führt dann wieder zu mehr Segmentierung. Damit wäre Rückwärtskompatibilität für Community Store Plugins um so wichtiger. Und das zieht wiederum nach sich, dass ich auf unabsehbare Zeit meine ganzen legacy extJs View Extensions mitschleppen und aktuell halten muss. Ich spüre den Schmerz der Shopware Entwickler in der Hinsicht ja, aber ich muss den update-willigen Kunden dann auch verklickern, warum vorher zig Anpassungen an Backend-Plugins notwendig werden.

2 Likes

Hallo,

ich würde gerne noch einmal das Thema aufgreifen, da ja die finale Version von Shopware Version 5.2.0 nicht mehr ewig auf sich warten lassen wird.

Wie würde man im Best Case genau vorgehen?

In der Install()-Funktion prüfen, ob eine Version größer oder gleich 5.2.0 eingesetzt wird und dann:

if ($this->assertMinimumVersion('5.2')) {
     $this->get('shopware_attribute.crud_service')->create(
          's_articles_attributes',
          'foobaer_1',
          'integer',
          [
               'label' => 'Foobaer 1',
               'displayInBackend' => true
          ]
     );
}

nutzen, und wenn die Version unter 5.2.0 ist, weiterhin:

Shopware()->Models()->addAttribute(
     's_articles_attributes',
     'foobaer',
     '1',
     'integer',
     true,
     null
);

$metaDataCache = Shopware()->Models()->getConfiguration()->getMetadataCacheImpl();
$metaDataCache->deleteAll();
	 
Shopware()->Models()->generateAttributeModels(
     array('s_articles_attributes')
);

 

In der Update()-Funktion dann das gleiche, nur bei einer Version größer oder gleich 5.2.0:

if ($this->assertMinimumVersion('5.2')) {
    $this->get('shopware_attribute.crud_service')->update(
        's_articles_attributes',
        'foobaer_1',
        'foobaer_1',
        'integer',
        [
            'label' => 'Foobaer 1',
            'displayInBackend' => true
        ]
    );
}

Oder muss ich bei der Update-Funktion gar nicht auf die Shopware-Version prüfen, damit bei einem späteren Update des Systems alles bereits vorgefertigt ist? Oder muss ich das neue Update für die alten Versionen ausschließen, damit nur Shopbetreiber das Plugin updaten können, die 5.2.0 einsetzen?

Sollte man so verfahren?

Beste Grüße

Sebastian

Hi,

wir haben die API vom Crud Service noch einmal überarbeitet. Es gibt hier jetzt nur noch die update Funktion. Siehe dazu: Attribute system

Wenn das Plugin auch unter 5.2 kompatibel sein soll, musst du einen Versions switch einbauen. Also genau so wie du es beschrieben hast.

 

1 Like

Hallo Oliver,

das ist natürlich super, wenn man nur noch die update()-Funktion nutzen muss, egal ob man das Feld anlegen oder nur aktualisieren will. Danke Smile.

Muss ich das Update nur für die Einblenden, die Shopware Version 5.2.0 nutzen, oder kann ich das auch für alle freigeben („bereite“ ich mit $this->get(‚shopware_attribute.crud_service‘)->update() das Feld nur „vor“, oder zerhaut es mir dadurch auch das Verhalten der Felder bei eine Shopware Version unter 5.2.0) [@Oliver Skroblin](http://forum.shopware.com/profile/1871/Oliver Skroblin „Oliver Skroblin“)‍ ?

Kann ich auch weiterhin von " extends Shopware_Components_Plugin_Bootstrap"  ableiten oder muss ich das Plugin umbauen, das es von „Plugin“ ableitet (um die Services nutzen zu können)?

Danke für die (ausführlichere) Dokumentation Halo.

Beste Grüße

Sebastian

 

Unter 5.2 kannst du nicht auf den Service  ‘shopware_attribute.crud_service’ zugreifen da dieser erst mit 5.2 eingefügt wurde. Daher hier der Versions check.

Die update Methode erstellt/aktualisiert zunächst nur ein Element in der Datenbank. Um es im Backend anzuzeigen musst du entsprechend die Konfiguration mit übergeben (siehe doku dazu).

Der Service selbst (sprich der crud_service) kannst du im alten und im neuen Plugin system verwenden. Dieser hat darauf keine Abhängigkeit.

@Oliver Skroblin schrieb:

Unter 5.2 kannst du nicht auf den Service  ‘shopware_attribute.crud_service’ zugreifen da dieser erst mit 5.2 eingefügt wurde. Daher hier der Versions check.

Die update Methode erstellt/aktualisiert zunächst nur ein Element in der Datenbank. Um es im Backend anzuzeigen musst du entsprechend die Konfiguration mit übergeben (siehe doku dazu).

Der Service selbst (sprich der crud_service) kannst du im alten und im neuen Plugin system verwenden. Dieser hat darauf keine Abhängigkeit.

Hallo,

also kann ich weiterhin:

class SwagAttribute extends Shopware_Components_Plugin_Bootstrap {
     ...
}

verwenden und muss nicht unbedingt auf:

class SwagAttribute extends Plugin {
     ...
}

wechseln?

Sollte man am besten das Update nur für 5.2.0 freigeben?

Beste Grüße

Sebastian

Also… entweder baust du ein Plugin auf dem neuen System, was dann auch nur mit 5.2 lauffähig ist, da es erst ab dann das neue System gibt. 

Wenn du jedoch auch die 5.1 z.B. mit supporten willst musst du das ganze auf dem alten System bauen. Dann darfst du auch nicht von der 

Shopware\Components\Plugin; Klasse ableiten, da es diese erst ab 5.2 gibt.

Genauso wie der CrudService vom AttributeBundle, dieser wurde erst mit 5.2 eingebaut, sprich den kannst du nur mit einem vorherigen Versionscheck  verwenden. 

1 Like

Hallo,

ich habe wohl den Fehler bei mir gefunden: scheinbar darf man seit Shopware Version 5.2.0 keine Großbuchstaben mehr in den Spaltennamen verwenden - nenne ich das Feld nämlich einfach attr_myfield, klappt alles (da selbst attr_MyField2 nicht funktioniert hat, kann es nur an der Großschreibung liegen). Das macht es natürlich nicht besser, da mein Spaltenname nunmal einen Großbuchstaben im Namen hat.

Mit diesem Code funktioniert es leider nicht (obwohl ja in shopware/README.md at 5.2 · shopware/shopware · GitHub so beschrieben), den Spaltennamen komplett in Kleinbuchstaben umzuwandeln:

$this->get('shopware_attribute.crud_service')->update(
     's_articles_attributes',
     'attr_MyField',
     'attr_myfield',
     'html',
     [
          'label' => 'MyField',
          'translatable' => true,
          'displayInBackend' => true,
          'position' => 1,
          'custom' => false
     ]
);

Bei dem Code kommt folgende Fehlermeldung:

Unable to update, got exception: An exception occurred while executing 'INSERT INTO s_attribute_configuration (table_name, column_name, column_type, entity, label, help_text, support_text, translatable, display_in_backend, custom, position, array_store) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params [null, null, null, null, null, null, null, 0, 0, 0, 0, null]: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'table_name' cannot be null 

Ich gehe davon aus, dass das deshalb nicht funktioniert, da der alte und der neue Spaltenname (in dem Sinne) ja gleich sind - sich eben nur durch zwei Großbuchstaben unterscheiden und er deshalb die Spalte nicht neu erstellt.

Beste Grüße

Sebastian

Als Entwickler und Shop-Betreiber bin ich von der neuen Attributverwaltung sehr hin- und hergerissen. Einerseits finde ich es sehr positiv, dass das Thema mal eine solide Basis bekommt und man in Zukunft (hoffentlich) einfacher mit den Attributen arbeiten kann.

Anderseits bin ich wie viele andere hier auch sehr unzufrieden mit dem neuen Ansatz, dass die Attribute quasi nun standardmäßig auf den Bereich „Freitextfelder“ beschränkt werden sollen und nur (wieder) durch Rumgefrickel dort herausgenommen werden können, ohne dass es dafür einen standardisierten Weg geben soll. Wo ist denn da letztendlich der Vorteil für den Shopbetreiber, für den letztendlich Shopware doch entwickelt wird?

Welcher Shopbetreiber möchte denn seine verschiedenen Anpassungen thematisch durcheinandergewürfelt am Ende einer Detailseite versteckt haben? Meiner Meinung nach für ein so modernes System wie Shopware ein vollkommen falscher Ansatz und ein großer Schritt rückwärts in der Flexibilität. Für Plugin-Entwickler, die einfach nur Geld machen wollen und denen Usability unwichtig ist, mag das zwar ein willkommender Weg sein, aber ich kann mir nicht vorstellen, dass das im allgemeinen Interesse der Community entwickelt wurde.

Ich hoffe, an dem Konzept wird noch gearbeitet und Fre itextfelder können in Shopware auch wirklich frei verwendet werden und nicht müssen nicht aufgrund der Codebasis so eingeschränkt werden. :frowning:

@carl schrieb:

Als Entwickler und Shop-Betreiber bin ich von der neuen Attributverwaltung sehr hin- und hergerissen. Einerseits finde ich es sehr positiv, dass das Thema mal eine solide Basis bekommt und man in Zukunft (hoffentlich) einfacher mit den Attributen arbeiten kann.

Anderseits bin ich wie viele andere hier auch sehr unzufrieden mit dem neuen Ansatz, dass die Attribute quasi nun standardmäßig auf den Bereich “Freitextfelder” beschränkt werden sollen und nur (wieder) durch Rumgefrickel dort herausgenommen werden können, ohne dass es dafür einen standardisierten Weg geben soll. Wo ist denn da letztendlich der Vorteil für den Shopbetreiber, für den letztendlich Shopware doch entwickelt wird?

Welcher Shopbetreiber möchte denn seine verschiedenen Anpassungen thematisch durcheinandergewürfelt am Ende einer Detailseite versteckt haben? Meiner Meinung nach für ein so modernes System wie Shopware ein vollkommen falscher Ansatz und ein großer Schritt rückwärts in der Flexibilität. Für Plugin-Entwickler, die einfach nur Geld machen wollen und denen Usability unwichtig ist, mag das zwar ein willkommender Weg sein, aber ich kann mir nicht vorstellen, dass das im allgemeinen Interesse der Community entwickelt wurde.

Ich hoffe, an dem Konzept wird noch gearbeitet und Fre itextfelder können in Shopware auch wirklich frei verwendet werden und nicht müssen nicht aufgrund der Codebasis so eingeschränkt werden. :(

Hallo,

ich würde auch eher dazu neigen zu sagen, dass es von Shopware auch nicht mehr gewünscht ist, dass man eigene Freitextfelder außerhalb des Freitextfeld-Fieldsets platziert - sonst gäbe es dafür ja einen Workaround oder zumindestens eine Doku, wo es mit einem Beispiel erklärt ist. Und man muss sich auch immer die Frage stellen: selbst wenn es durch irgendein “rumgefrickel” möglich wäre, die eigenen Freitextfelder außerhalb des Fieldsets zu platzieren - wie lange noch? Es ist ja nicht der Weg, den Shopware selbst wünscht - man soll ja schließlich das Freitextfeld-Fieldset von Shopware nutzen. Hier wäre dann also auch wieder zu bedenken, ob der “Workaround” dann überhaupt noch lange funktioniert und auch das platzieren außerhalb irgendwann ganz entfallen muss. Ich würde also nicht sagen, das ein Hersteller da “nur das große Geld machen will”, sondern einfach nur die Shopware - Regeln einhalten möchte und zukunftsorientiert entwickelt. Zumal es dafür ja nicht mal eine (shopware-konforme) Dokumentation gibt, wie es außerhalb vom Fieldset weiterhin (gut) funktionieren kann - nicht jeder Onlineshop hat schließlich das beste Hosting im Hintergrund.

Da Shopware 5.2.0 laut Aussage von Shopware noch diesen Monat erscheinen wird, wird auch die neue Freitextfeld-Verwaltung so bestehen bleiben.

Beste Grüße

Sebastian

 

Aus Sicht der Usability und eines Shopbetreiber der nicht über eine WAWI arbeitet, sondern im Backend selber die Daten pflegt, ist es ein Unding bei Eingaben die eigentlich zusammen gehören runter und rauf zu scrollen. Auch macht es das Ganze unübersichtlicher!

Auch verstehe ich nicht so ganz was es für einen Vorteil für Shopbetreiber haben soll, wenn Sie jetzt einfach per Klick überall ein Freitextfeld erzeugen können. Die entsprechenden Ausgaben/Logiken müssen ja trotzdem im Frontend selber eingebaut werden!?

Hallo zusammen,

ich habe das Ganze noch einmal etwas in den DevDocs dokumentiert, wie man die Felder außerhalb des Fieldsets positionieren und verarbeiten kann. Falls dieser noch ergänzt werden sollte, lasst es mich wissen.

Den Guide findet ihr unter Attribute system

LG, Jan

4 Likes

@Jan Bücker schrieb:

Hallo zusammen,

ich habe das Ganze noch einmal etwas in den DevDocs dokumentiert, wie man die Felder außerhalb des Fieldsets positionieren und verarbeiten kann. Falls dieser noch ergänzt werden sollte, lasst es mich wissen.

Den Guide findet ihr unter https://developers.shopware.com/developers-guide/attribute-system/#move-attribute-fields-into-anoth

LG, Jan

Hallo Jan,

danke für deine Mühe.

Ich konnte das soweit für mich adaptieren. Ich erzeuge ein eigenes Fieldset mit eigenem Feld durch:

//{block name="backend/article/view/detail/window" append}

Ext.define('Shopware.apps.Article.view.detail.MyWindow', {
	/**
     * Defines an override applied to a class.
     * @string
     */
    override: 'Shopware.apps.Article.view.detail.Window',

	createBaseTab: function() {
		var me = this;
 
        /* Call the original method and store its result */
        var panelTab = me.callParent(arguments);
 
		me.field = Ext.create('Ext.form.field.Text', {
			name: 'attribute[attrField]',
			fieldLabel: 'Mein Feld',
            allowBlank: false,
            anchor:'100%',
            labelWidth:150,
			translatable: true,
			translationName: 'attrField',
        });
		
		/* Create new FieldSet with the new panel inside */
		fieldset = Ext.create('Ext.form.FieldSet', {
            layout: 'anchor',
            title: 'Fieldset',
            items: [
                me.field 
			]
		});	
 
        /* After the overridden createBaseTab method was called, save to access the detailForm attribute */
        me.detailForm.insert(1, fieldset);
 
        /* Return original method's result */
        return panelTab;
    },
    onStoresLoaded: function() {
        var me = this;

        me.callParent(arguments);

        Ext.Ajax.request({
            url: '{url controller=AttributeData action=loadData}',
            params: {
                _foreignKey: me.article.get('mainDetailId'),
                _table: 's_articles_attributes'
            },
            success: function(responseData, request) {
                var response = Ext.JSON.decode(responseData.responseText);

                me.field.setValue(response.data['__attribute_attr_field']);
            }
        });
    }
});
//{/block}

Das Laden klappt somit problemlos.

Nur beim Speichern komme ich nicht weiter, da ich nicht genau weiss, beim welchem “Einstiegspunkt” ich einsetze könnte, da sich mein Feld ja nicht im Base-Fieldset befindet:

__attribute_attr_field: me.getBaseFieldSet().attrField.getValue()

Hast du eine Idee, wie ich da ansetzen müsste?

Beste Grüße

Sebastian

1 Like

Schau dir mal in themes/Backend/ExtJs/backend/article/controller/detail.js die Property refs an. Dort findest du Referenzen, die du z.B. per me.getBaseFieldSet() respektive me.getMainWindow() aufrufen kannst. Das sind im Prinzip fertige Selektoren für die einzelnen Windows, Fieldsets usw.

LG, Jan

@Jan Bücker schrieb:

Schau dir mal in themes/Backend/ExtJs/backend/article/controller/detail.js die Property refs an. Dort findest du Referenzen, die du z.B. per me.getBaseFieldSet() respektive me.getMainWindow() aufrufen kannst. Das sind im Prinzip fertige Selektoren für die einzelnen Windows, Fieldsets usw.

LG, Jan

Hallo Jan,

ich habe gestern noch eine Lösung gefunden, die so auch funktioniert:

me.getDetailForm().getForm().getFieldValues()['attribute[attrField]']

Wäre diese Lösung Best Practise?

 

Kann es sein, dass deine Lösung (Attribute system) nicht für Varianten möglich ist? Wenn ich onStoresLoaded bei meiner Varianten-Datei analog der window-Datei hinschreibe, wird die Funktion nicht ausgeführt und der Inhalt nicht in das Feld geladen (habe auch einfach mal einen console-Log-Befehl hinzugefügt, der wird nicht ausgegeben, also wird bei Varianten scheinbar onStoresLoaded nicht genutzt). Das wird sicher auch daran liegen, das es in der detail.js nicht wie in der window.js in der initComponent() keinen Einstiegspunkt gibt, oder? Diesen hier gibt es nur in der window.js:

me.on('storesLoaded', me.onStoresLoaded, me);

Somit kann man sich bei Varianten nirgends einklicken, um den Inhalt reinzuladen, oder? Zum Speichern könnte man sich ja maximal bei saveVariant dranhängen.

Die Lösung ist ja somit für Variantenartikel-Freitextfelder nicht einsetzbar, oder?

Beste Grüße

Sebastian