[HowTo] zusätzliche Artikel-Attribute in Frontend + Backend

Hallo zusammen, ich hab auf Basis des Thread “Hinzufügen eines 2. Beschreibungstextes für Produkt” von jensfiedler sowie der Developer-Schulung vom vergangengen Montag nun erfolgreich weitere Attribute zum Artikel-Stamm hinzugefügt und sie sowohl im Frontend als auch im Backend erreichbar gemacht. :smiley: Das Ergebnis möchte ich hier allen zur Verfügung stellen. Wer den Code übernehmen möchte, sollte darauf achten, das Präfix von “my” in etwas sinnvolles zu ändern. Im Anschluss habe ich noch eine Frage betreffend der Ausgabe im Backend. zunächst die [color=blue]bootstrap.php[/color]: [code]<?php class Shopware_Plugins_Backend_additionalArticleAttributes_Bootstrap extends Shopware_Components_Plugin_Bootstrap
{
public function getVersion()
{
return ‘1.0.0’;
}

public function getLabel()
{
    return 'zusätzliche Artikel-Attribute';
}

public function getInfo()
{
    return array(
        'version' => $this-\>getVersion(), 'label' =\> $this-\>getLabel(), 'description' =\> ''); } public function getCapabilities() { return array( 'install' =\> true, 'enable' =\> true, 'update' =\> false ); } public function install() { /\* Model erweitern \*/ $this-\>addAttributes(); /\* Event-Listener für Frontend-Erweiterung: Artikel-Detailseite \*/ $this-\>subscribeEvent( 'Shopware\_Modules\_Articles\_GetArticleById\_FilterArticle', 'onArticle' ); /\* Event-Listener für Backend-Erweiterung \*/ $this-\>subscribeEvent( 'Enlight\_Controller\_Action\_PostDispatch\_Backend\_Article', 'postDispatchBackendArticle' ); return array('success' =\> true, 'invalidateCache' =\> array('backend', 'proxy')); } public function uninstall() { /\* Model-Erweiterungen wieder löschen \*/ $this-\>removeAttributes(); return true; } /\* Sub-Routinen für Install \*/ private function addAttributes() { $metaDataCache = Shopware()-\>Models()-\>getConfiguration()-\>getMetadataCacheImpl(); $metaDataCache-\>deleteAll(); Shopware()-\>Models()-\>addAttribute( 's\_articles\_attributes', 'my', 'Additional\_Attribute\_One', 'varchar(255)', true, null ); Shopware()-\>Models()-\>addAttribute( 's\_articles\_attributes', 'my', 'Additional\_Attribute\_Two', 'varchar(255)', true, null ); $metaDataCache = Shopware()-\>Models()-\>getConfiguration()-\>getMetadataCacheImpl(); $metaDataCache-\>deleteAll(); Shopware()-\>Models()-\>generateAttributeModels( array('s\_articles\_attributes') ); } /\* Sub-Routinen für Uninstall \*/ private function removeAttributes() { $metaDataCache = Shopware()-\>Models()-\>getConfiguration()-\>getMetadataCacheImpl(); $metaDataCache-\>deleteAll(); Shopware()-\>Models()-\>removeAttribute( 's\_articles\_attributes', 'my', 'Additional\_Attribute\_One' ); Shopware()-\>Models()-\>removeAttribute( 's\_articles\_attributes', 'my', 'Additional\_Attribute\_Two' ); $metaDataCache = Shopware()-\>Models()-\>getConfiguration()-\>getMetadataCacheImpl(); $metaDataCache-\>deleteAll(); Shopware()-\>Models()-\>generateAttributeModels( array('s\_articles\_attributes') ); } /\* Event-Listener Funktion(en) im Backend \*/ public function postDispatchBackendArticle(Enlight\_Event\_EventArgs $args) { $args-\>getSubject()-\>View()-\>addTemplateDir( $this-\>Path() . 'Views/' ); //if the controller action name equals "load" we have to load all application components. if ($args-\>getRequest()-\>getActionName() === 'load') { $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/additionalArticleAttributes/article/model/article.js' ); $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/additionalArticleAttributes/article/view/detail/base.js' ); } } /\* Event-Listener Funktion(en) im Frontend \*/ public function onArticle(Enlight\_Event\_EventArgs $args) { $sArticle = $args-\>getReturn(); $additionalAttributes = $this-\>getAdditionalArticleAttributes($sArticle["articleID"]); if($additionalAttributes) { foreach($additionalAttributes as $additionalAttributeName =\> $additionalAttributeValue) { $sArticle[$additionalAttributeName] = $additionalAttributeValue; } } return $sArticle; } /\* eigene Funktionen \*/ private function getAdditionalArticleAttributes($articleID) { /\* \* gibt ein assoziatives Array mit den Feldnamen und deren Inhalte \* der zusätzlichen Eigenschaften-Felder dieses Plugins zurück \*/ $dbResult = Shopware()-\>Db()-\>fetchAll( "SELECT at.my\_Additional\_Attribute\_One ,at.my\_Additional\_Attribute\_Two FROM s\_articles\_attributes at INNER JOIN s\_articles a ON a.id = at.articleID WHERE a.id = ?",array($articleID)); return $dbResult[0]; /\* fetchAll gibt folgendes zurück: \* array(2) { \* [my\_Additional\_Attribute\_One] =\> string(nnn) "(Wert)" \* [my\_Additional\_Attribute\_Two] =\> string(nnn) "(Wert)" \* } \*/ } /\* protected functions \*/ protected $manager = null; protected function getManager() { if ($this-\>manager === null) { $this-\>manager = Shopware()-\>Models(); } return $this-\>manager; } }[/code] Nun noch die Dateien zur Erweiterung von Model und View im Backend. Bitte die Ordner-Struktur gemäß [i]postDispatchBackendArticle[/i] in der bootstrap.php beachten: [color=blue][b]article.js[/b][/color] [code]//{block name="backend/article/model/attribute/fields" append} { name: 'myAdditionalAttributeOne', type: 'string' }, { name: 'myAdditionalAttributeTwo', type: 'string' }, //{/block}[/code] [color=blue][b]base.js[/b][/color] [code]//{block name="backend/article/view/detail/base" append} Ext.override(Shopware.apps.Article.view.detail.Base, { createRightElements: function() { var me = this, fields = me.callParent(arguments); fields.push({ xtype: 'textfield', name: 'attribute[myAdditionalAttributeOne]', translatable: false, allowBlank: true, fieldLabel: 'zusätzliches Attribut 1' }); fields.push({ xtype: 'textfield', name: 'attribute[myAdditionalAttributeTwo]', translatable: false, allowBlank: true, fieldLabel: 'zusätzliches Attribut 2' }); return fields; } }); //{/block}[/code] Der Aufruf im Frontend ist gemäß Event-Listener nun auf der Artikel-Detailseite möglich. Zum Testen einfach mal folgenden Code in das lokal angepasste Template aufnehmen: [code]

zusätzliches Attribut 1: {$sArticle.my_Additional_Attribute_One}

zusätzliches Attribut 2: {$sArticle.my_Additional_Attribute_Two}

[/code] Damit haben wir 2 neue Attribute, die man im Backend und Frontend sehen kann. Analog könnte man natürlich noch mehr machen. Und sicher könnte man die Aufrufe zum Anlegen, löschen und Platzieren im Backend noch verbessern, aber so fand ich es verständlicher. [color=red]Wichtiger Hinweis:[/color] Ich habe nicht umsonst in den Bezeichnern die Zahlen ausgeschrieben! Natürlich hatte ich erst Additional_Attribute_1 und Additional_Attribute_2 verwendet. Es gab zwar keine Fehlermeldung, im Backend wurden die Inhalte aber weder gespeichert noch angezeigt. (Frontend habe ich nicht mehr geprüft.) Der Bug-Tracker bekommt gleich noch Bescheid hierzu. [color=red]Ganz wichtiger Hinweis:[/color] Es gibt noch massive Probleme mit dem Import-/Export-Plugin! Die XML-Ausgabe gibt mir zwar die Felder aus (als myAdditionalAttributeOne und myAdditionalAttributeTwo), einen Import habe ich aber noch nicht erfolgreich durchgeführt. Viel schlimmer noch: Sobald das Model erweitert wurde, stürzt der CSV-Export ab! :shock: Fehlermeldung: SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘at.myAdditionalAttributeOne’ in ‘field list’ in Zend/Db/Statement/Pdo.php on line 234 Auch dies wird noch an den Bug-Tracker gemeldet. [color=green]Nun zu meiner Frage:[/color] Ich habe ewig gebraucht, um die Felder in die Eingabemaske im Backend zu bekommen. (Vor allem deshalb, weil man nicht einfach vom Beispiel-Plugin “ExtendBackendExample5” der Developer-Schulung abschreiben kann: Dort reichten name und fieldLabel für die Erweiterung von fields.) Kann mir jemand erklären, wie ich die Felder im Backend unter die ab Werk vorhandenen “Zusatzfelder” bekomme? Gruß, Nico.

UPDATE Ich hab endlich heraus gefunden, wie man die zusätzlichen Attribute in den Abschnitt Zusatzfelder bekomme! :sunglasses: Eigentlich ist es sogar einfacher, da man ohne Modifikationen am View mittels Plugin auskommt. Dafür hat man etwas mehr händisch nachzuarbeiten: Die Zusatzfelder müssen bekanntlich im Backend unter [Einstellungen]->[Grundeinstellungen]->[Artikel]->[Artikel-Freitextfelder] erstmal angemeldet werden. Dort wird unter „Name“ der Feldname, also „attr1“, „attr2“, etc., eingetragen. Hinzu kommt noch ein Feld-Typ, ein (sinnvoller) Bezeichner für die Eingabemaske usw. Wenn man hier einen anderen Namen als „att1“…„attr20“ einträgt, nimmt das Backend dies gelassen entgegen. Die Eingabemaske zum Artikel wird hübsch erweitert, nur gibt es keine Verbindung zwischen Eingabefeld und Datenbank. Alles, was man tun muss, ist ein anderes Model für das Backend zu erweitern. Und das hatte ich prinzipiell schon getan: Das Model für diesen Bereich ist attribute. Man findet das Original unter /templates/_default/backend/article/model/attribute.js. In der article.js wurde es auch schon passend erweitert. Der Ordnung halber sollte man die Datei aber umbenennen in attribute.js. Danach wird in der [color=blue]bootstrap.php[/color] die Function postDispatchBackendArticle geändert zu public function postDispatchBackendArticle(Enlight\_Event\_EventArgs $args) { $args-\>getSubject()-\>View()-\>addTemplateDir( $this-\>Path() . 'Views/' ); if ($args-\>getRequest()-\>getActionName() === 'load') { $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/additionalArticleAttributes/article/model/attribute.js' ); } } Wie gesagt kann die bisherige Erweiterung des Views entfallen. Alles, was man nun noch tun muss, ist die Attribute in den Grundeinstellungen anzumelden. Bitte beachtet, dass man nicht den Namen des DB-Feldes, sondern den Feldnamen des Models eintragen muss. In diesem Fall trägt man also unter Name z. B. „myAdditionalAttributeOne“ ein und nicht etwa „my_Additional_Attribute_One“ oder gar „Additional_Attribute_One“. Voila: Zusätzliche Felder, erreichbar unter „Zusatzfelder“. Wenn jetzt noch das Import-/Export-Plugin mitspielen würde… :frowning:

Hallo zusammen, ich hab dieses Plugin als Grundlage für weitere Gehversuche in Shopware genommen und eine neue Funktionalität eingebaut: Anstelle wie bisher die Felder an meherern Stellen im bootstrap zu wiederholen, habe ich nun eine Datei namens config.php hinzu gefügt, welche ein Array mit meinen Attributen enthält: [color=blue]config.php[/color] <?php return array( 'attributes' => array( 'prefix' =\> 'my', 'items' =\> array( array( "name"=\>"Attr\_One", "type"=\>"varchar(255)", "nullable"=\>true, "default"=\>null ), array( "name"=\>"Attr\_Two", "type"=\>"varchar(255)", "nullable"=\>true, "default"=\>null ) ) ) ); Frage 1: Wie bindet man am besten diese Config-Datei ein? Um die Datei nicht mehrmals öffnen zu müssen, wollte ich sie an einer Zentralen stelle laden und das Array in einen Member meiner Klasse übertragen. Zuerst wollte ich den Konstruktor erweitern und das Laden dort vornehmen. Laut Dokumentation auf php.net ist dies möglich. Aber der Code function \_\_construct() { parent::\_\_construct(); /\* meine Erweiterungen \*/ } führt gleich mal zum Absturz des Plugin-Managers, noch bevor das Plugin überhaupt installiert ist. Deshalb wollte ich eine Methode verwenden, welche prüft, ob die Member-Eigenschaft meiner Klasse schon mit Daten gefüllt ist und, falls nicht, dies erledigt. Ab dem 2. Aufruf zur Laufzeit entfällt somit der Zugriff auf die externe Datei: protected $pluginConfig = null; public function getConfig() { if (!$this-\>pluginConfig) $this-\>pluginConfig = include(dirname(\_\_FILE\_\_) . DIRECTORY\_SEPARATOR . 'Config.php'); return $this-\>pluginConfig; } Beim Aufruf dieser Methode ist mir die Syntax noch nicht ganz klar. Folgendes funktioniert innerhalb der anderen Methoden: $config = $this-\>getConfig(); $prefix=$config['prefix'] Folgendes funktioniert (leider) nicht: $prefix=$this-\>getConfig['prefix'] Aber sowas wäre deutlich kürzer… Frage 2: Nach welchem Schema wird aus einem DB-Feldnamen ein Feldname des Models? Ich würde nämlich gern die Model-Erweiterung in [color=blue]attribute.js[/color] beim Installieren anhand der Config-Datei vom PHP erzeugen lassen. Dass aus dem DB-Feldnamen my_Additional_Attribute_One der Model-Feldname myAdditionalAttributeOne wird, ist mir nun bekannt; aber wie lautet das genaue Regelwerk? Gruß, Nico.

Hallo Nico, warum du den Konstruktor nicht überladen kannst, weiß ich leider auch nicht, zu deiner Methode habe ich allerdings eine Idee: $prefix=$this-\>getConfig['prefix']; Dies funktionierte nicht, da du ja auf eine Funktion und nicht auf ein Array zugreifst. (Du könntest allerdings direkt auf $this->pluginConfig[‚attributes‘][‚prefix‘] zugreifen.) Ansonstent probier mal folgendes: public function getConfig($param = null) { $ret = false; if (!$this-\>pluginConfig) { $this-\>pluginConfig = include(dirname(\_\_FILE\_\_) . DIRECTORY\_SEPARATOR . 'pconf.php'); } if ( is\_null($param) ) { $ret = $this-\>pluginConfig; } elseif ( isset($this-\>pluginConfig['attributes'][$param]) ) { $ret = $this-\>pluginConfig['attributes'][$param]; } return $ret; } Jetzt bekommst du z.B. mit $this->getConfig(‚prefix‘); den Eintrag ‚prefix‘ aus dem Array ‚attributes‘ zurück. Falls du noch tiefer möchtest, also z.B. direkt einzelne Einträge aus ‚items‘, musst du die Methode entsprechend umbauen.

[quote=“akeon_shop”]$prefix=$this-\>getConfig['prefix']; Dies funktionierte nicht, da du ja auf eine Funktion und nicht auf ein Array zugreifst.[/quote] So ungefähr lautete auch die Fehlermeldung vom Backend… [quote=“akeon_shop”]Du könntest allerdings direkt auf $this->pluginConfig[‘attributes’][‘prefix’] zugreifen.[/quote] Aber dafür müsste $pluginConfig erstmal geladen sein; und ein eigener Konstruktor, der sinnigerweise genau das übernehmen sollte, scheitert bekanntlich… Ich hab meine getConfig-Methode jetzt ungefähr nach deinem Vorschlag umgesetzt; vorerst mit Parametern für 2 Ebenen. Schön ist anders, aber es reicht soweit. Danke dafür! An dem anderen Problem hänge ich immer noch. Hat niemand eine Ahnung, nach welchem Schema aus einem DB-Feldnamen ein Feldname des Models wird? Gruß, Nico.

Hi basti, hast du das schon ausprobiert? Eigentlich müsste es funktionieren. Sobald ich meine 5 anderen Baustellen wieder versorgt habe, werd ich das mal einbauen und testen… Gruß, Nico.

Ja, es funktioniert, finde es allerdings unschön an 20 verschiedenen Stellen die Artikelattribute einzugeben. Wenn ich mit den anderen Teilen meines Plugins fertig bin, werde ich das noch mal überarbeiten und das Ergebnis dann posten. Solltet ihr vorher bereits funktionierenden Code haben, würde ich mich darüber natürlich freuen.

Hallo zusammen, Hallo basti, ich hab inzwischen die Attributs-Liste in einer zentralen Datei ausgelagert und das automatische Anlegen der Eingabe-Felder im Backend eingebaut. Hier zunächst mal die Konfigurationsdatei [color=blue]config.php[/color]: <?php return array( 'attributes' => array( 'prefix' =\> 'my', 'items' =\> array( array( 'label'=\>'einmal boolean', 'helptext'=\>'speichert einen boolschen Wert, also 0 oder 1', 'name'=\>'FieldOne', 'type'=\>'boolean', 'nullable'=\>true, 'default'=\>null ), array( 'label'=\>'einfacher String', 'helptext'=\>'speichert eine kleine Zeichenkette\r\n (hier: bis zu 64 Zeichen)', 'name'=\>'FieldTwo', 'type'=\>'varchar(64)', 'nullable'=\>true, 'default'=\>null ) ) ) ); Um die Konfigurationsdatei zu laden, werden zunächst eine neue Eigenschaft und eine neue Methode in die Bootstrap-Klasse eingefügt: /\* lokale Config-Datei laden \*/ protected $pluginConfig = null; public function getConfig($pLevel1 = null, $pLevel2 = null) { $ret = false; if (!$this-\>pluginConfig) { $this-\>pluginConfig = include(dirname(\_\_FILE\_\_) . DIRECTORY\_SEPARATOR . 'Config.php'); } if ( is\_null($pLevel1) ) { $ret = $this-\>pluginConfig; } elseif ( isset($this-\>pluginConfig[$pLevel1]) ) { if ( is\_null($pLevel2) ) { $ret = $this-\>pluginConfig[$pLevel1]; } elseif ( isset($this-\>pluginConfig[$pLevel1][$pLevel2]) ) { $ret = $this-\>pluginConfig[$pLevel1][$pLevel2]; } } return $ret; } Die Methode getConfig ruft also die Konfig-Datei auf und liest die Inhalte. Falls dies bereits in einem vorigen Aufruf geschehen ist, greift sie aber auf den Member $pluginConfig zu. Dies erspart ständiges Lesen von der Festplatte. Alle Methoden, die auf die Attribute zugreifen, müssen nun ihre Informationen über getConfig holen: private function addAttributesToModel() { /\* Model erweitern \*/ $metaDataCache = Shopware()-\>Models()-\>getConfiguration()-\>getMetadataCacheImpl(); $metaDataCache-\>deleteAll(); foreach($this-\>getConfig('attributes','items') as $attribute) { Shopware()-\>Models()-\>addAttribute( 's\_articles\_attributes', $this-\>getConfig('attributes','prefix'), $attribute['name'], (($attribute['type']=='boolean') ? 'varchar(5)' : $attribute['type']), $attribute['nullable'], $attribute['default'] ); } $metaDataCache = Shopware()-\>Models()-\>getConfiguration()-\>getMetadataCacheImpl(); $metaDataCache-\>deleteAll(); Shopware()-\>Models()-\>generateAttributeModels( array('s\_articles\_attributes') ); } private function createBackendModelExtensionFile() { /\* js-Extension generieren, um Felder in Artikel-Eingabemaske zu zeigen \*/ foreach($this-\>getConfig('attributes','items') as $attribute) { $strBackendModelAttributes .= " { name: '".$this-\>getConfig('attributes','prefix').str\_replace("\_", "", $attribute['name'])."', type: 'string' },\r\n"; } $handle = fopen(dirname(\_\_FILE\_\_) . DIRECTORY\_SEPARATOR . "Views". DIRECTORY\_SEPARATOR . "backend". DIRECTORY\_SEPARATOR . "additionalArticleAttributes". DIRECTORY\_SEPARATOR . "article". DIRECTORY\_SEPARATOR . "model". DIRECTORY\_SEPARATOR . "attribute.js", "w"); fwrite($handle, "//{block name=\"backend/article/model/attribute/fields\" append}\r\n". $strBackendModelAttributes. "//{/block}\r\n"); fclose($handle); } private function removeAttributesFromModel() { $metaDataCache = Shopware()-\>Models()-\>getConfiguration()-\>getMetadataCacheImpl(); $metaDataCache-\>deleteAll(); foreach($this-\>getConfig('attributes','items') as $attribute) { Shopware()-\>Models()-\>removeAttribute( 's\_articles\_attributes', $this-\>getConfig('attributes','prefix'), $attribute['name'], $attribute['type'], $attribute['nullable'], $attribute['default'] ); } $metaDataCache = Shopware()-\>Models()-\>getConfiguration()-\>getMetadataCacheImpl(); $metaDataCache-\>deleteAll(); Shopware()-\>Models()-\>generateAttributeModels( array('s\_articles\_attributes') ); } private function getAdditionalArticleAttributes($articleID) { /\* \* gibt ein assoziatives Array mit den Feldnamen und deren Inhalte \* der zusätzlichen Eigenschaften-Felder dieses Plugins zurück \*/ $prefix = $this-\>getConfig('attributes','prefix'); foreach($this-\>getConfig('attributes','items') as $attribute) { $arrAttributeList[] = 'at.'.$prefix."\_".$attribute['name']. ' AS '. '\''.$prefix.str\_replace("\_", "", $attribute['name']).'\''; } $strAttributeList = Implode(", " , $arrAttributeList); Shopware()-\>Log()-\>info($strAttributeList); $dbResult = Shopware()-\>Db()-\>fetchAll( "SELECT $strAttributeList FROM s\_articles\_attributes at INNER JOIN s\_articles a ON a.id = at.articleID WHERE a.id = ?",array($articleID)); return $dbResult[0]; } Wie gesagt, werden die Eingabefelder im Backend jetzt auch automatisch generiert. Allerdings hab ich bislang nur erfolgreich Strings und Booleans angelegt; andere Feldtypen hab ich schlichtweg noch nicht gebraucht. Boolean war übrigens ein Krampf: Es ist nicht möglich, im Backend mit einem Feld zu arbeiten, welches in der Datenbank als „boolean“ angemeldet wurde. Das Backend benötigt hier ein VarChar mit einer Mindestgröße von 5 Bytes, weil nicht etwa 0 und 1 sondern „false“ und „true“ als Strings gespeichert werden! Dies ist der Grund für die kleine If-Abfrage in Zeile 13 von addAttributesToModel. Hier die zugehörigen Methoden (zu laden in Install bzw. Uninstall): private function addAttributesToBackendForm() { /\* Eingabefelder in Backend-Maske [Einstellungen]-\>[Grundeinstellungen]-\>[Artikel]-\>[Artikel-Freitextfelder] eintragen \*/ foreach($this-\>getConfig('attributes','items') as $attribute) { $attributeType = ltrim(rtrim(strtolower($attribute['type']))); /\* if (substr($attributeType,0,7)=='varchar' || substr($attributeType,0,8)=='nvarchar') $backendFieldType = 'text'; \*/ if ($attributeType=='boolean') { $backendFieldType = 'boolean'; } else { $backendFieldType = 'text'; } $insert = Shopware()-\>Db()-\>query( "INSERT INTO `s_core_engine_elements` ( `type`, `label`, `required`, `position`, `name`, `variantable`, `help`, `translatable` ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )" , array( $backendFieldType, $attribute['label'], 0, 0, $this-\>getConfig('attributes','prefix').$attribute['name'], 0, $attribute['helptext'], 0 ) ); } } private function removeAttributesFromBackendForm() { /\* Eingabefelder in Backend-Maske [Einstellungen]-\>[Grundeinstellungen]-\>[Artikel]-\>[Artikel-Freitextfelder] eintragen \*/ foreach($this-\>getConfig('attributes','items') as $attribute) { $delete = Shopware()-\>Db()-\>query( "DELETE FROM `s_core_engine_elements` WHERE name = ?" , array($this-\>getConfig('attributes','prefix').$attribute['name'] ) ); } } So, ich hoffe, dass ich nichts vergessen habe. Ansonsten bitte Antwort Posten oder PN senden… Gruß, Nico.

1 „Gefällt mir“

Ich bin gerade auf der Suche nach einer Möglichkeit beim Kauf eines Artikels (also beim Klick auf „In den Warenkorb“) diesem zusätzliche Informationen mitzugeben. Ist das hier vorgeschriebene Verfahren dafür angebracht? Also ganz einfaches Beispiel: Benutzer ist in der Artikeldetailansicht, klickt auf „In den Warenkorb“ und ich hole mir per JavaScript die aktuelle Zeit und möchte diese mit dem gekauften Artikel verbinden. Es soll nachher also möglich sein in den Bestellungen sowohl für den Admin als auch für den Käufer diese Daten einzusehen. Hoffe das war verständlich. LG

Hallo Argo, ich hab Shopware eine Zeit lang liegen lassen, daher bin ich ein wenig aus der Materie raus. Ich glaube aber, Dein Ansatz ist für dieses Vorhaben nicht ganz der richtige: Frage 1: Willst Du wirklich zu jedem Artikel in der Bestellung angeben, wann er in den Warenkorb gelegt wurde? Der Zeitpunkt der Bestellung ist am Ende ja ein anderer; denn die Bestellung erfolgt ja erst nach Angabe von Adresse, Zahlungsbedingungen, etc. Frage 2: Falls Du das do so wie beschrieben willst, dann brauchst Du hierzu immer noch nicht einen Artikel modifizieren, sondern die Position im Warenkorb. Dazu braucht man nicht unbedingt weitere Artikel-Attribute anlegen, sondern kann ja auch eines der 20 ab Werk vorhandenen nutzen. Schau Dir mal die Übergabe in den Warenkorb an. Eventuell reicht es sogar schon aus, ein Hidden-Input einzubauen, welches per JavaScript den Zeitstempel beim Submit erhält. Das Input muss dann eines der freien attr-Felder füllen. Soweit ich weiß, werden die dann in den Warenkorb übernommen. Natürlich müssen dann noch diverse Templates angepasst werden, um das Attribut auch anzuzeigen… Gruß, Nico.

Hallo Nico, danke schonmal für deine Antwort. Zu Frage 1: Im Prinzip nicht die Uhrzeit, aber andere Informationen die wichtig für den Artikel sind. Das mit der Uhrzeit war nur ein Beispiel. Ich habe im DOM bereits entsprechende Variablen registriert und auch gefüllt. Sobald jetzt jemand auf “In den Warenkorb” klickt, sollen diese Informationen eben dazu gespeichert werden. Ich habe als Artikel beispielsweise eine Tasse. Über ein selbst geschriebenes Frontend kann die Farbe der Tasse und ein Bild ausgewählt werden, welches auf die Tasse gedruckt werden soll. Sobald dieser Dialog geschlossen wurde, speichere ich mir die Daten in einer JavaScript-Variable zwischen und lege den Artikel automatisch in den Warenkorb. Irgendwie muss ich jetzt ja aber auch noch die eingestellten Werte mit dazu abspeichern. Zu Frage 2: Kannst du mir hierzu weitere Hilfestellungen zur Verfügung stellen? Wo kann ich mir den Übergabe in den Warenkorb anschauen? Aber genau irgendwie so hatte ich das vor. Eventuell einfach einen Hidden-Input einbauen und dort den Wert der JavaScript Variable ablegen. Ich würde mich wirklich sehr freuen, wenn du hier etwas präziser werden könntest, denn das könnte genau der mir noch fehlende Schritt sein! LG, Argo

Hallo Argo, ich hab leider derzeit eine Menge anderer Baustellen außerhalb von Shopware; deshalb kann ich Dir im Moment wenig Hilfe geben. Hast du schon versucht, die 20 Attribute zu befüllen, die es ab Werk gibt? (Zusätzlich gäbe es inzwischen auch ein kostenloses Plugin von Shopware mit 20 weiteren Attributen.) Ansonsten müsstest Du Dir mal den Controller ansehen, der beim Klick auf “in den Warenkorb” angesteuert wird, und sehen, was der macht. Die Klasse sBasket solltest Du Dir auch mal ansehen. Wie gesagt, ich bin derzeit auf anderen Baustellen beschäftigt und gedanklich ziemlich aus Shopware raus. Tut mir Leid… Es gibt für Deine Anforderungen ja auch zwei (fast) fertige Plugins, aber die kosten zwischen 200 und 300 Euro. Such mal im Store unter “individuelle Optionen”. Eventuell lohnt sich eines davon, bevor Du wochenlang selbst an der Aufgabe tüftelst. MfG, Nico.

Hallo Nico, die Attribute können meines Erachtens doch nicht geändert werden, oder? Die sind doch nur für Zusatzangaben zu einem Artikel zu gebrauchen, habe ich immer gedacht. Selbst wenn ich die jedes mal ändern würde, dann füge ich die Informationen doch nicht zu dem Artikel im Warenkorb hinzu sondern allgemein zu diesem Artikel, oder verstehe ich da jetzt was total falsch? Natürlich existieren dafür schon fertige Plugins, die aber auch vollkommen oversized und -powered sind. Ich möchte ja einfach nur einen String zusätzlich abspeichern, mehr irgendwie nicht. Und für ein Hobbyprojekt ist mir das leider viel zu teuer :-/… Danke aber wiedermal für deine Hilfe!

Hallo Nico, zu deiner Frage zum __construct: man muss im __construct 1(optional 2) Parameter bekommen und weiter an Parent (Shopware_Components_Plugin_Bootstrap) übergeben: public function \_\_construct($name, $info = null) { $this-\>setConfig(); parent::\_\_construct($name, $info); } Grüße, Alexei