Observer
Ein Observer wird ausgeführt, wenn ein Event getriggert wird. Um einen Observer in Magento 2 zu erstellen, legen wir zunächst eine Klasse im Ordner Observer an. In unserem Beispiel erstellen wir die Datei Observer/ProductLoadInjecter.php:<?php
namespace Tudock\HelloWorld\Observer;
use Magento\Framework\Event\Observer;
class ProductLoadInjecter implements \Magento\Framework\Event\ObserverInterface {
public function execute(\Magento\Framework\Event\Observer $observer) {
$model = $observer->getData('data_object');
$model->setData('tudock_helloworld','Hello Observer!');
}
}
Ein Observer implementiert das Interface \Magento\Framework\Event\ObserverInterface, welches wiederum die Methode execute hat. Diese Methode bekommt als Argument ein Objekt, in dem der Kontext des Events gespeichert ist. Mit getData können Event-spezifische Informationen aus dem Observer extrahiert werden.
Unser Beispiel-Observer wird sich an das Event catalog_product_load_after hängen, wird also ausgeführt nachdem ein Produkt geladen wurde.
In data_object befindet sich für dieses Event das Product-Model. An diesem Produkt-Model setzen wir beispielhaft den Wert tudock_helloworld auf einen Text, den wir nachher zum Testen auslesen werden.
Observer registrieren
Damit unser Observer auch ausgeführt wird, müssen wir ihn für das Event registrieren. Je nachdem ob wir wollen, dass unser Observer im Frontend- oder im Backend-Kontext ausgeführt wird, erstellen wir dafür eine Datei events.xml unter etc/frontend oder etc/adminhtml. Wir legen für unser Beispiel die Datei unter app/etc/frontend/events.xml an:<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="catalog_product_load_after">
<observer name="helloworld_inject" instance="Tudock\HelloWorld\Observer\ProductLoadInjecter" shared="false" />
</event>
</config>
Diese XML-Datei enthält event Knoten. Der name der Knoten gibt an, bei welchem Event unser Observer ausgeführt wird.
Innerhalb des event Knoten folgen beliebig viele observer Knoten, welche die Observer für das Event definieren. Jeder Observer braucht zumindest einen beliebigen name und die Klasse (instance), die unseren Observer repräsentiert.
Unseren Observer testen
Um den Observer zu testen, lassen wir uns das Datenfeld tudock_helloworld, das wir an jedes Produkt anhängen, in unserem HelloProduct Block ausgeben. Dafür definieren wir zunächst eine neue Methode im HelloProduct Block:
public function getObserverText() {
return $this->getProduct()->getData('tudock_helloworld');
}
Danach können wir im Template diesen Text ausgeben:
<p><?php echo $block->getObserverText(); ?></p>
Helper
Helper sind einfache Singleton-Klassen, die häufig verwendete (Hilfs-)Funktionen auslagern. Helper werden im Ordner Helper angelegt und können beliebig benannt werden. In Anlehnung an den Standard-Helper in Magento 1 heißt der Helper in diesem Modul Data, aber es kann beliebig viele Helper mit beliebigen Namen geben. Der Helper liegt unter Helper/Data.php:<?php
namespace Tudock\HelloWorld\Helper;
class Data extends \Magento\Framework\App\Helper\AbstractHelper {
public function getSomeColor() {
return 'rgb('.rand(0,255).','.rand(0,255).','.rand(0,255).')';
}
}
Jeder Helper sollte (muss aber nicht) \Magento\Framework\App\Helper\AbstractHelper erweitern. Unser Beispiel-Helper hat eine Methode, die eine zufällige CSS Farbe generiert.
Helper einbinden
Um einen Helper einzubinden, wird dieser einfach (ohne Factory, da Singleton) per Dependency Injection in eine Klasse geladen. In unserem Beispiel laden wir den Helper in den HelloProduct Block: /* … */
protected $_dataHelper;
public function __construct(
\Magento\Catalog\Block\Product\Context $context,
\Magento\Framework\Stdlib\ArrayUtils $arrayUtils,
array $data,
\Tudock\HelloWorld\Model\ResourceModel\HelloText\CollectionFactory $helloTextCollectionFactory,
\Tudock\HelloWorld\Helper\Data $dataHelper
) {
parent::__construct($context, $arrayUtils, $data);
$this->_helloTextCollectionFactory = $helloTextCollectionFactory;
$this->_dataHelper = $dataHelper;
}
/* … */
Wir können den Helper jetzt benutzen, wie wir wollen. Für unsere Zwecke legen wir in der Klasse eine neue Methode an:
public function getColor() {
return $this->_dataHelper->getSomeColor();
}
In diesem Beispiel leiten wir die Anfrage für eine Farbe an unseren Helper weiter, welcher eine zufällige CSS-Farbe generieren kann. Diese Farbe können wir nun im Template verwenden.
Unser Template sieht nach allen Änderungen ungefähr so aus:
<p style="color:<?php echo $block->getColor() ?>">
<?php echo __('Hello') ?> , <?php echo $block->getProductName(); ?>!
</p>
<p>
<a href="<?php echo $block->getHelloWorldUrl() ?>">
<?php echo $block->getText() ?>
</a>
</p>
<p style="color:<?php echo $block->getColor() ?>">
<?php echo $block->getObserverText(); ?>
</p>
Wenn alles geklappt hat, sollte der Block auf der ADS nun ungefähr so erscheinen:
Mein Fazit zur Magento 2 Modulentwicklung
Mit Magento 2 hat sich so einiges geändert. Es gibt aktuell noch viele Probleme (auf Github allein gibt es über 1000 Issues), aber es hat sich auch einiges verbessert:
Die Modulentwicklung ist nun weitaus klarer gekapselt und Module sind viel weniger voneinander abhängig, dank Dependency Injection und Service Layer. Auch die ganze Modulverwaltung hat sich durch Composer endlich stark vereinfacht. Das XML-Chaos ist vorbei. Statt wie in Magento 1 alle möglichen Angaben doppelt und dreifach in einer großen XML Datei zu machen zu müssen, erkennt Magento 2 viele Dinge auf Anhieb.
Aber besonders im Frontend-Workflow (auf den ich in dieser Serie nur am Rande eingegangen bin) gibt es noch einiges an Nachholbedarf und einige Probleme, die das Arbeiten mit Magento 2 derzeit noch sehr stark erschweren.
Viele Themen habe ich hier noch nicht angesprochen (Plugins/Preferences, LESS, Javascript, Cronjobs etc.) – also wenn ihr ein Thema besonders interessant findet, lasst es uns wissen! Wir werden uns bemühen, eure Vorschläge in weiteren Artikeln aufzugreifen.
Aber fürs Erste ist diese Blogserie nun vorbei. Nichstdestotrotz laden wir euch ein, mit uns im Austausch zu bleiben. Die Kommentarfunktion unter diesem Blogbeitrag bietet eine gute Gelegenheit, um Fragen zu stellen und Antworten zu erhalten oder Anregungen für weitere Artikel zum Thema Magento 2 zu platzieren. Wir freuen uns auf euer Feedback!
Und zum Schluss noch einmal der Hinweis, dass das gesamte Demo-Modul auch auf Github verfügbar ist.
Die weiteren Beiträge der Serie
- Magento 2 Modulentwicklung – Teil 1: Vorbereitung
- Magento 2 Modulentwicklung – Teil 2: Frontend Entwicklung
- Magento 2 Modulentwicklung – Teil 3: Controller und Actions
- Magento 2 Modulentwicklung – Teil 4: Models und Dependency Injection
- Magento 2 Modulentwicklung – Teil 5: Wichtige Objekte
- Magento 2 Modulentwicklung – Teil 6: Resource Models und Install-Scripts