Türchen 05: Widgets in Magento

Sie bieten Shopbetreibern nützliche Funktionalitäten, ohne dass diese Programmierkenntnisse mitbringen müssen. Entwickler können sie ohne großen Aufwand implementieren. Sie können bereits seit geraumer Zeit erstellt werden, nämlich seit Magento 1.4, das im Februar 2010 erschienen ist.

Dennoch hört man erstaunlich wenig von Widgets. Ich gebe zu, dass auch bei unseren Kunden bisher wenig Interesse besteht und ich daher selten Widgets umgesetzt habe. Doch das sollte sich ändern: es ist höchste Zeit, diese Helferlein etwas näher vorzustellen. In diesem Türchen sehen wir uns die Konfigurationsmöglichkeiten von Widgets an.

Was ist ein Widget?

Vielleicht fragt ihr euch gerade: wovon spricht der überhaupt? Das habt ihr nicht wirklich gefragt, oder? Falls doch, dann ab zur offiziellen Magento-Website und die Einführung zu Magento-Widgets lesen.

Im Prinzip handelt es sich um bei Widgets um Block-Klassen mit vordefinierten Konfigurationsmöglichkeiten. Sie können in den Content-Bereichen von CMS-Seiten etc. eingebunden und über Formulare im Backend einfach konfiguriert werden.

Standard-Widgets

Bei der Installation von Magento 1.6 CE werden 8 Widgets mitgeliefert:

  • CMS Page Link: Hiermit kann auf eine statische Seite verlinkt werden. Der Link wird in einer eigenen Zeile ("Link Block Template") oder mitten im Fließtext ("Link Inline Template") angezeigt.
  • CMS Static Block: Dient zum Einfügen eines statischen CMS-Blocks.
  • Catalog Category Link: Verlinkt zu einer Kategorieseite, wiederum in einer eigenen Zeile oder im Fließtext.
  • Catalog New Products List: Stellt eine beliebige Anzahl neuer Produkte dar, entweder in der Listen- oder Gitter-Ansicht. Die Darstellung kann gecacht werden.
  • Catalog Product Link: Was für eine Überraschung, man kann auch auf Produkte verlinken! Die Möglichkeiten sind dieselben wie bei den Kategorie- und CMS-Links.
  • Orders And Returns: Dieses Widget dient vermutlich dazu, Bestellungen und Retouren einzusehen. Ich muss zugeben, dass ich es noch nie verwendet habe und dass es in meiner Demo-Installation von 1.6.1.0 auch nicht funktioniert.
  • Recently Compared Products: Stellt eine beliebige Anzahl an Produkten dar, die der Kunde kürzlich verglichen hat (in Grid- oder Listen-Darstellung). Allerdings wird auch dieses Widget in der Demo-Installation nicht angezeigt.
  • Recently Viewed Products: Stellt eine beliebige Anzahl an Produkten dar,, die der Kunde kürzlich angesehen hat (in Grid- oder Listen-Darstellung).

Eigene Widgets erstellen

Habt ihr Blut geleckt, dann könnt ihr Türchen 23 des letztjährigen Adventkalenders öffnen und lesen, wie man Widgets in Magento erstellt. Mit dieser Basis sind wir gewappnet, diese Jahr einen noch genaueren Blick auf Widgets zu werfen.

Grund-Angaben

Nehmen wir für unser Kalendertürchen an, dass wir ein Youtube-Widget haben möchten. Dafür erstellen wir die Extension Emzee_Youtube. Welche Dateien dafür nötig sind, könnt ihr im letztjährigen Artikel nachlesen. Wir wenden uns direkt der Konfigurationsdatei widget.xml zu und sehen uns das grundlegende XML an:
<?xml version="1.0" encoding="UTF-8"?>

<widgets>

    <emzee_youtube_embed type="emzee_youtube/widget" module="emzee_youtube" translate="name description">

        <name>Youtube-Video</name>

        <description type="desc">Einbetten eines Youtube-Videos</description>

        <!--<is_email_compatible>1</is_email_compatible>-->

        <parameters />

    </emzee_youtube_embed>

</widgets>
  • Am Anfang geben wir unserem Widget einen eindeutigen Identifier, hier emzee_youtube_embed. Wir legen mit type die Block-Klasse fest (sie muss Mage_Widget_Block_Interface implementieren) und können wie gewohnt mit translate XML-Nodes übersetzbar machen.
  • name definiert den offiziellen Namen, der im Dropdown der Widget-Auswahl angezeigt wird.
  • description wird unterhalb des Dropdowns angezeigt, sobald man das Widget ausgewählt hat.
  • Mit is_email_compatible = 1 kann das Widget in E-Mails verfügbar gemacht werden.
  • In parameters werden die Konfigurationsmöglichkeiten definiert, die der Shopbetreiber über das Formular vornehmen kann. Diesen Punkt sehen wir uns gleich genauer an.

Konfiguration von Widgets

Jetzt kommen wir zum spannenden Teil, den Parametern. Durch sie wird es den Händlern möglich, das Widget selbst zu konfigurieren. Hier haben wir ein Beispiel für unser einfaches Youtube-Widget mit einem einzelnen Parameter:
widget_youtube_simple-650x323
Das dafür nötige XML sieht wie folgt aus:
<?xml version="1.0" encoding="UTF-8"?>

<widgets>

    <emzee_youtube_embed type="emzee_youtube/widget" module="emzee_youtube" translate="name description">

        <name>Youtube-Video</name>

        <description type="desc">Einbetten eines Youtube-Videos</description>

        <parameters>

            <youtube_id translate="label description">

                <label>Youtube-Id</label>

                <description><![CDATA[Sie finden die ID in der Video-URL, z.B. http://www.youtube.com/watch?v=<strong>y_WTlIuzwRg</strong>]]></description>

                <visible>1</visible>

                <required>1</required>

                <type>text</type>

                <value>123456</value>

            </youtube_id>

        </parameters>

    </emzee_youtube_embed>

</widgets>
  • Zu Beginn definieren wir einen Identifier, einen Namen für den Parameter. Dieser sollte gut gewählt werden, denn man greift über ihn später auf den Wert zu.
  • Das label steht für den Namen des Parameters, der im Dropdown etc. angezeigt wird.
  • Mit description kann eine Erklärung zu dem Parameter angegeben werden. Sie wird unterhalb des Parameters eingeblendet.
  • visible = 1 gibt an, dass das Element sichtbar ist. Ist der Wert 0 oder nicht definiert, dann wird ein hidden-Formularelement erzeugt.
  • Bei einer Angabe von required = 1 muss der Parameter zwingend konfiguriert werden.
  • Durch type wird der Typ des Eingabefelds definiert. Im Beispiel fügt text ein einzeiliges Textfeld ein. Mit den verschiedenen Typen setzen wir uns gleich noch genauer auseinander.
  • Mit value kann ein Standardwert festgelegt werden.

Die Konfigurationslemente

Im Hintergrund des Konfigurationsformulars werkt eine normale Klasse Varien_Data_Form_Element_Fieldset. Und das heißt: man kann theoretisch jedes Formularelement verwenden, das im Verzeichnis Varien_Data_Form_Element zur Verfügung gestellt wird. In der Praxis bekommt man jedoch leider nicht alle Elemente problemlos zum Laufen. Ich gebe euch ein paar Beispiele, was leicht möglich ist.
  • Einzeiliges Textfeld Ein simples Eingabefeld wird wie folgt definiert:
    <type>text</type>
    Mitkann ein Standardwert vorgegeben werden.
  • Einfache Auswahl (Dropdown) Für ein Dropdown gibt man an:
    <type>select</type>
    Natürlich muss man auch die Auswahlmöglichkeiten definieren. Das passiert entweder direkt im XML:
    <values>
    
    	<identifier1 translate="label">
    
    		<value>1</value>
    
    		<label>Eins</label>
    
    	</identifier1>
    
    	<identifier2 translate="label>
    
    		<value>2</value>
    
    		<label>Zwei</label>
    
    	</identifier2>
    
    </values>
    Oder indem man ein Source-Model angibt:
    <source_model>emzee_youtube/widget</source_model>
    Das Source-Model (in diesem Fall Emzee_Youtube_Model_Widget) muss die Methode toOptionArray() implementieren und ein Array mit assoziativen Arrays zurück geben:
    public method toOptionArray()
    
    {
    
        return array(
    
            array('label' => 'Das Label', 'value' => 'Der Wert'),
    
            array('label' => 'Das Label 2', 'value' => 'Der Wert 2')
    
        );
    
    }
    Auch hier kann ein Standardwert mit angegeben werden. Man gibt dazu den Wert der jeweiligen Option an: im ersten Beispiel2, im zweiten BeispielDer Wert 2.
  • Mehrfachauswahl (Multiselect) Die Mehrfachauswahl ist dem einfachen Select-Element sehr ähnlich. Als einzigen Unterschied schreibt man bim Typ:
    multiselectxml Möchte man mehrere Werte als Standard vorgeben, schreibt man sie komma-separiert in die value-Node:
    <value>1,2</value>
  • Zeitangabe Wer eine Zeitangabe mit Stunden, Minuten und Sekunden benötigt, verwendet:
    <type>time</type>

Ein kleines Beispiel

Hier sehen wir nun ein kleines Beispiel, wie ein Widget mit den oben angegebenen Parametern aussehen könnte:
widget_youtube_example-650x652
Das XML für dieses Widget:
<?xml version="1.0" encoding="UTF-8"?>

<widgets>

    <emzee_youtube_embed type="emzee_youtube/widget" module="emzee_youtube" translate="name description">

        <name>Youtube-Video</name>

        <description type="desc">Einbetten eines Youtube-Videos</description>

        <parameters>

            <youtube_id translate="label description">

                <label>Youtube-Id</label>

                <description><![CDATA[Sie finden die ID in der Video-URL, z.B. http://www.youtube.com/watch?v=<strong>y_WTlIuzwRg</strong>]]></description>

                <visible>1</visible>

                <required>1</required>

                <type>text</type>

                <value>123456</value>

            </youtube_id>

            <resolution translate="label description">

                <label>Auflösung</label>

                <description>Die Auflösung des Videos in Pixeln (mit vordefinierten Werten)</description>

                <visible>1</visible>

                <required>1</required>

                <type>select</type>

                <value>1920x1080</value>

                <values>

                    <res480x360 translate="label">

                        <value>480x360</value>

                        <label>480x360 (4:3)</label>

                    </res480x360>

                    <res1920x1080 translate="label">

                        <value>1920x1080</value>

                        <label>1920x1080 (4:3)</label>

                    </res1920x1080>

                </values>

            </resolution>

            <resolution_source_model translate="label description">

                <label>Auflösung</label>

                <description>Die Auflösung des Videos in Pixeln (mit Source Model)</description>

                <visible>1</visible>

                <required>1</required>

                <type>select</type>

                <value>1920x1080</value>

                <source_model>emzee_youtube/resolutions</source_model>

            </resolution_source_model>

            <textarea>

                <label>Beschreibung</label>

                <description>Beschreibung des Videos</description>

                <visible>1</visible>

                <type>textarea</type>

            </textarea>

            <share_options translate="label description">

                <label>Sharing-Links</label>

                <description>Welche Sharing-Links sollen angeboten werden?</description>

                <visible>1</visible>

                <required>1</required>

                <type>multiselect</type>

                <value>facebook,twitter</value>

                <values>

                    <facebook translate="label">

                        <value>facebook</value>

                        <label>Facebook</label>

                    </facebook>

                    <googleplus translate="label">

                        <value>googleplus</value>

                        <label>Google+</label>

                    </googleplus>

                    <twitter translate="label">

                        <value>twitter</value>

                        <label>Twitter</label>

                    </twitter>

                    <xing translate="label">

                        <value>xing</value>

                        <label>XING</label>

                    </xing>

                </values>

            </share_options>

            <time>

                <label>Uhrzeit</label>

                <visible>1</visible>

                <type>time</type>

            </time>

        </parameters>

    </emzee_youtube_embed>

</widgets>

Geht noch mehr?

Guess what: das war noch nicht alles, was sich über Widgets schreiben lässt. So ist es möglich,
  • anstatt eines Varien_Data_Form-Elements eine beliebige eigene Klasse zu verwenden.
  • einen Helper-Block zu definieren, der anschließend an das eigentliche Form-Element eingebunden wird. Das verwendet Magento für die Produkt- und Kategorieauswahl.
  • Abhängigkeiten zwischen Formular-Elementen einzubauen.
  • den Code mit der richtigen Herangehensweise mit minimalem Aufwand- sowohl als normalen Block in beliebigen Teilen des Webshops als auch als Widget in Template-Blöcken zu verwenden.- in verschiedenen Themes / Store-Views unterschiedlich zu gestalten.
Wir haben bisher nur an der Oberfläche gekratzt. Wer will, kann wesentlich fortgeschrittenere Widgets bauen. Doch das ist eine andere Geschichte.

Darstellung im TinyMCE-Editor

Leider gibt es im Editor keine Vorschau, wie das Widget mit den gewählten Einstellungen aussieht. (Falls ihr eine Umsetzung dafür kennt, meldet euch bitte in den Kommentaren!) Man kann aber zumindest seinem Widget durch ein eigenes Icon Individualität verleihen. Magento sucht im Verzeichnis [magentoroot]/skin/adminhtml/[package]/[theme]/images/widget/ nach einer GIF-Datei mit einem Dateinamen, der sich an der Klassen-Id des Widgets orientiert. Die Klassen-Id ist der String, der mit type="" angegeben wird. Im obigen Beispiel haben wir für das Widget die Block-Klassen-Id "emzee_youtube/widget" angegeben. Für den Dateinamen ersetzen wir den Schrägstrich durch zwei Unterstriche und hängen .gif an. Somit müssen wir unser Icon unter [magentoroot]/skin/adminhtml/[package]/[theme]/images/widget/emzee_youtube__widget.gif ablegen.

Fazit

Ich hoffe, ihr habt ein wenig Gefallen daran gefunden, euch intensiver mit Widgets auseinander zu setzen. Falls ihr gute Widgets kennt oder vielleicht sogar selbst welche entwickelt hat, freue ich mich über Meldungen in den Kommentaren. :)


Ein Beitrag von Matthias Zeis
Matthias's avatar

Matthias Zeis lebt in Wien und ist für Onlineshop-Projekte bei LimeSoda zuständig. Er arbeitet seit 2009 mit Magento, ist seit 2011 Magento Certified Developer und organisiert seit 2012 den ersten Magento-Stammtisch Österreichs. Wer Lust auf mehr bekommen hat, findet Matthias bei matthias-zeis.com, LimeSoda, Twitter (@mzeis) oder GitHub.

Alle Beiträge von Matthias

Kommentare
Matthias Zeis am

Hallo Michael,

hier ist der letztjährige Artikel: http://www.webguys.de/magento/turchen-23-widgets-in-magento-erstellen/

Grüße Matthias

Micha am

Hallo Matthias,

da ich mich seit einigen Monaten intensiv mit Magento auseinander setzte, würd ich nun gerne mehr mit Widgets arbeiten. Ich finde deinen Beitrag klasse und ausführlich. Leider kam ich nur zu dem Punkt "...erstellen wir die Extension Emzee_Youtube. Welche Dateien dafür nötig sind, könnt ihr im letztjährigen Artikel nachlesen."

Ich finde den Beitrag zu der Extension aber nicht, um die Grundlage damit zu erstellen. Kannst du mir weiterhelfen?

Danke im Vorraus und Grüße nach Wien, Michael

Matthias Zeis am

Ich weiß von keinen Neuigkeiten dazu.

Florin P. am

Danke für den tollen beitrag, gute übersicht. Bloß das thema editor hätte mich mehr interessiert, gibts da was neue dazu?

Matthias Zeis am

Wenn ich dich richtig verstehe, kannst du das lösen, indem du einen eigenen Form-Element-Typ erstellst.

Das User-Interface könnte ähnlich aussehen wie bei den Tier Prices. Außerdem musst du dafür sorgen, dass die Daten sinnvoll abgespeichert werden. Magento verwendet für solche Fäll gerne ein Serialized-Array-Backend: https://github.com/LokeyCoding/magento-mirror/blob/magento-1.7/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Serialized/Array.php

Michael am

Das Tutorial war mir bisher eine sehr große Hilfe. Nun habe ich einen Punkt der nicht so ohne weiteres lösbar scheint. Ich erstelle gerade ein Widget für die Erstellung einer Liste bei der die List Items in der Anzahl dynamisch sein soll.

Ist dies über die XML Einstellungen für das Widget möglich?

Cronjobs in Magento am

[...] entwickelt hat, bin ich auch dieses Jahr wieder mit einem Gastbeitrag dabei.2011 hatte ich über Widgets geschrieben. Heuer habe ich mich für ein wichtiges, aber häufig nicht genug beachtetes Thema [...]

Benjamin am

Auch ich muss mich leider zu dem Kreis zählen, der Widgets lange Zeit nicht entdeckt hat. Aber mittlerweile machen wir in der Agentur möglichst viel damit, um unsere Kunden vom HTML-Hacken in CMS-Seiten und Blöcken fern zu halten.

Danke für den Beitrag, Matthias!

Matthias Zeis am

Hallo Bernd,

spätestens wenn du einfache und doppelte Anführungszeichen zusammen verwenden willst, wirst du vermutlich auf Probleme stoßen.

Zuerst könntest du dich fragen: ist es wirklich nötig, dass der Shop-Admin HTML-Code schreibt? Schon alleine das ist fehleranfällig. Vielleicht reicht es, wenn ein Eingabefeld für das Id-Attribut und eines für den Inhalt des divs vorgesehen wird. Noch besser ist es, wenn der Kunde die Id gar nicht selbst eingibt, sondern du aufgrund anderer Eingaben entscheiden kannst, welche Id in HTML zu vergeben ist. Falls der Shop-Admin mehr als nur ein simples div wie im Beispiel eingeben können soll, ist das für mich ein noch stärkeres Zeichen, dass man ein robusteres Konzept finden könnte/sollte.

Und wenn dir das alles nicht hilft, sondern du den Shop-Admin einfach HTML eingeben lassen möchtest: überlege, ob du eine alternative Syntax verwenden kannst (zum Beispiel in Richtung BB-Code - http://en.wikipedia.org/wiki/BBCode), die ohne Anführungszeichen auskommt.

bernd am

ich bin noch recht neu bei magento dabei. Um so mehr freue ich mich über die diversen Hilfen und Dokumentationen wie diese zu Magento. Mit Hilfe der Blogeinträge habe ich auch ein Widget gebastelt und es mit Parametern versehen. Nur habe ich ein Problem, wenn ich Anführungszeichen in den Paramtern habe (zb. wenn ich dort ein HTML-Tag inkl. Attributen eingeben lassen möchte). Bei der Einbindung des Widgets wird ja so etwas ähnliches wie HTML erstellt und dann gibt es Syntaxfehler, so dass die Parameter gar nicht (sauber) bis in meinen PHP-Code kommen (von der Konfusion des Editors, der dann 'aufräumt' mal ganz abgesehen).


{{widget type="Test/widget" tag="hallo"}}
                                ^        ^    ^            ^

mein aktueller Ausweg: manuell die äußeren Anführungszeichen (") gegen Hochkommatas (') austauschen.

{{widget type="Test/widget" tag='hallo'}}
                                ^                          ^

Aber was ist wenn ich mal beides brauche? Oder ein unbedarfter Shop-Admin nicht darauf achtet? Insbesondere wenn er den Editor benutzt.

Gastbeitrag bei Webguys: Widgets in Magento am

[...] Ich fühle mich geehrt und habe natürlich zugesagt. Heute ist mein Gastbeitrag unter dem Titel Türchen 05: Widgets in Magento erschienen.In dem Artikel gehe ich zuerst auf die Frage ein, was ein Widget überhaupt ist und [...]

Matthias Zeis am

Hallo Michael und Fabrizio, danke für das Feedback und Lob!

Fabrizio Branca am

Toller Artikel, Matthias! Vielen Dank für die ausführliche Übersicht...

Michael am

Ja leider führen die Magento Widgets ein Schattendasein. Dies kommt meiner Meinung nach vor allem davon, dass viele Shop-Betreiber keinen größeren Wert auf die redaktionelle Gestaltung Ihres Online Shops legen. Aber sobald eine Firma Ihre Produkte etwas präsentieren möchte, kommt schon die Nachfrage nach einfachen Bausteinen für die Redakteure. Wer einmal selber ein Widget erstellt hat, auf Grund eurer schönen Anleitungen, wird es zukünftig immer öfters verwenden. Danke

Dein Kommentar