Attribut-Werte vor der Ausgabe im Frontend verändern

Für alle, die sich schon immer gefragt haben, wofür eigentlich der Catalog-Output-Helper ist, möchte ich in diesem Beitrag einmal ein wenig Licht ins Dunkel bringen. Um genau zu sein, geht es um folgende Zeilen

$_helper = $this->helper('catalog/output');
echo $_helper->productAttribute($_product, $_product->getDeliveryTime() , 'delivery_time');
// oder
echo $_helper->categoryAttribute($_category, $_category->getName(), 'name');

Warum sollte man also die Ausgabe eines Produktattributes noch einmal durch einen Helper schieben müssen? Man will doch einfach nur einen bestimmten Wert haben und sonst nichts, oder?

Der Grund ist ganz einfach: Durch verschiedene Handler ist es möglich, die Ausgabe eines jeden Attributes zu manipulieren. Die entsprechenden Handler müssen einfach nur im Output-Helper registriert werden, und schon kann man durchstarten.

Zum Start schauen wir uns einmal das Event catalog_helper_output_construct an. Dieses wird aufgerufen, wenn der Output-Helper instanziiert wird. Wir wir wissen, handelt es sich bei einem Helper immer um ein Singleton - so wird das Event also auch nur ein einziges Mal geworfen.

<frontend>
    <events>
        <catalog_helper_output_construct>
            <observers>
                <my_module>
                    <class>my_module/observer</class>
                    <type>singleton</type>
                    <method>catalogHelperOutputConstruct</method>
                </my_module>
            </observers>
        </catalog_helper_output_construct>
    </events>
</frontend>

Nun, wo wir über die Existenz des Helpers bescheid wissen, können wir unsere Handler registrieren. Da es sich um einen Catalog-Helper handelt, gibt es folgende zwei Möglichkeiten für Handler:

  • catalogAttribute
  • productAttribute

Aber wie registrieren wir nun so einen Handler? Das ist relativ einfach, hier mal ein Beispiel aus dem Observer:

class My_Module_Model_Observer
{
    public function catalogHelperOutputConstruct($observer)
    {
        /** @var $outputHelper Mage_Catalog_Helper_Output */
        $outputHelper = $observer->getHelper();

        $helper = Mage::helper('my_module');
        $outputHelper->addHandler('productAttribute', $helper);
    }
}

Wie man sieht, braucht man als erstes ein Objekt, welches das Handle-Event verarbeitet. Hier bietet sich ein Helper aus dem eigenen Modul an. Der einzige Anspruch an das übergebene Objekt ist eine Methode mit dem entsprechenden Handler-Typ (also catalogAttribute oder productAttribute). Diese wird nun für jedes Attribut aufgerufen - daher muss man selbst innerhalb der Methode prüfen, wie und ob man welches Attribut manipulieren möchte:

class My_Module_Helper_Data extends Mage_Core_Helper_Abstract
{
    public function productAttribute(Mage_Catalog_Helper_Output $outputHelper, $outputHtml, $params)
    {
        /** @var $product Mage_Catalog_Model_Product */
        $product = $params['product'];

        if ($params['attribute'] == 'name' && ($attributeValue = $product->getData($params['attribute']))) {
            $outputHtml = sprintf('<a href="%s" title="%s">%s</a>', $product->getProductUrl(), $product->getName(), $outputHtml);
        }

        return $outputHtml;
    }
}

Über den ersten Parameter $outputHelper bekommt man die Instanz des Helpers noch einmal in die Methode hereingereicht, $outputHtml ist die Ausgabe an das Frontend - dieser stellt sicherlich in den meisten Fällen eine Grundlage für eine manipulierte Ausgabe dar. Über den dritten Parameter bekommt man weitere Informationen zum Attribut, wie zum Beispiel das betroffene Produkt oder eben die entsprechende Kategorie.

Die Anwendungsmöglichkeiten sind vielfältig. So könnte man

  • ein Attribut anders ausgeben, wenn sich ein Produkt in einer bestimmten Kategorie befindet,
  • aus einer übergebenen SKU einen Link erstellen
  • den Wert an das entsprechende Länderformat anpassen
  • und vieles mehr

Durch die vielfältigen Möglichkeiten sollte man darauf achten, dass man nicht versucht jedes Problem über diesen Weg zu erschlagen. Man sollte sich immer vor Augen halten, dass jede Ausgabe eines Attributs durch dieses Stück Code laufen wird. Fängt man hier nun an, noch großartig Logik zu hinterlegen oder gar Objekte aus der Datenbank zu laden, kann man hier schnell ein paar Performance-Killer schreiben.

Natürlich kann man beliebige weitere Typen von Handlern hinzufügen, diese müssen dann aber manuell über die Process-Methode verarbeitet werden. Spontan fällt mir aber kein Beispiel ein, wo das Sinn machen würde.



Ein Beitrag von Matthias Kleine
Matthias's avatar

Matthias Kleine hatte Mitte 2012 die ersten Kontakte mit Magento - dies geschah durch die Anstellung bei der code-x GmbH als Softwareentwickler. Seit dem bildet er sich ständig im Bereich eCommerce fort, schreibt eigene Extensions und stellt diese gerne auch als OpenSource-Projekte auf GitHub zur Verfügung. Seit Ende 2013 wird Matthias auch im Verzeichnis der zertifizierten Magento-Entwickler gelistet. @klein0r

Alle Beiträge von Matthias

Kommentare
Manuel am

Hallo!

In welchen Fällen sollte man denn auf den outputhelper setzen und in welchen ein eigenes Frontend model benutzen und die Methode getvalue() überschreiben? Gibt es da eine Faustregel und bestimmte Anwendungsfälle?

Danke!

Henning am

Habe den Fehler gefunden. Ich benutze euer GroupAttribut Modul. Und da werden im Model vorher leere Attribute aussortiert, bevor der Output Helper in der Template Datei überhaupt aufgerufen wird. Deshalb auch keine Ausgabe. Trotzdem Danke für die schnelle Antwort!

Henning am

Also es funktioniert alles normal, sobald etwas eingetragen ist. Es ist ein normales Textfeld. Sagen wir ich trage ein "w" ein, dann durchläuft es alle Methoden und wird korrekt nach meinen Vorstellungen verändert. Sobad das Textfeld leer ist, wird die Funktion productAttribute des Output Helpers gar nicht erst aufgerufen. Ich umgehe es jetzt, indem ich standardmäßig ein "empty" eintrage und das dann abfange, ist aber keine schöne Lösung.

Matthias Kleine am

Mh ist mir so nicht bekannt - wäre es möglich, dass das Attribut gar nicht in dem Model enthalten ist? Also nicht mit zum Select der Collection hinzugefügt wurde?

Henning am

Super erklärt! Allerdings möchte ich ein Attribut verändern, wenn es leer ist. Ich habe aber festgestellt, dass ein leeres Attribut gar nicht erst in die Funktion productAttribute des Output Helpers gelangt und demzufolge auch nicht in meine eigene productAttribute Funktion gelangt.

Wie kann ich denn das Attribut dann vorher schon abgreifen? hat jemand eine Idee?

Nikolai Krambrock am

Sehr cooler und spezifischer Artikel!

Tobi am

Sehr cooles Thema, danke!

Dein Kommentar