Teil 4 meiner Blog-Reihe auf integer-net.com über Framework-unabhängigen Code ist draußen: Preparing Data For Output
Design Patterns für Framework-agnostische Extensions/Plugins – Bridge
Teil 3 meiner Blog-Reihe auf integer-net.com über Framework-unabhängigen Code ist draußen: Building Bridges
Vorige Teile
Design Patterns für Framework-agnostische Extensions/Plugins – Dependency Injection
Teil 2 meiner Blog-Reihe auf integer-net.com über Framework-unabhängigen Code ist draußen: Using Dependency Injection
Vorige Teile
Design Patterns für Framework-agnostische Extensions/Plugins
Meine neue Artikelreihe auf integer-net.com stellt nützliche Design Patterns für entkoppelte Magento Extensions vor, die in zwei Teile geteilt sind: Das Magento Modul und eine Framework-unabhängige (Framework-agnostische) Bibliothek, die für Magento 1 und Magento 2 wiederverwendbar ist. Die selben Prinzipien sind natürlich auch für weitere Frameworks und Anwendungen anwendbar.
Sie wird nicht den Refactoring-Prozess von bestehenden Extensions hin zu diesem Modell behandeln, das ist ein anderes Thema, das ich beim Developers Paradise 2016 in Kroatien präsentieren werde. Bleibt dran!
Im ersten Teil geht es um den Zugriff auf Konfigurationsdaten mit Configuration Value Objects.
Weiterlesen auf integer-net.com → (Englisch)
Zufällige Produkte in Magento anzeigen
Leider ist der Eintrag nur auf Englisch verfügbar.
Comparable Interface für PHP
Vor etwa 5-6 Jahren hatte ich meine “PHP sollte mehr wie Java sein” Phase und habe viel mit Sachen wie String Objekten und Überladen von Methoden experimentiert, was meistens fiese Workarounds erforderte und die meisten Dinge stellten sich auf lange Sicht nicht als sehr praktikabel heraus.
Aber ein Package aus der Zeit gefällt mir immer noch ziemlich gut, und zwar ComparatorTools, was immerhin Platz 2 in den monatlichen PHPclasses.org Innovation Awards belegte. Es stellt Comparable
und Comparator
Interfaces zur Verfügung sowie Funktionen, analog zu den Core Array-Funktionen, die mit diesen arbeiten können.
Interfaces
Die Interfaces ähneln den entsprechenden Java interfaces, außer dass wir keine Generics in PHP haben, so dass nicht garantiert werden kann, dass die verglichenen Objekte den selben Typ haben. Dies muss zur Laufzeit in der Implementierung geprüft werden, sofern nötig. Ein Exception-Typ für diese Fälle ist verfügbar:
interface Comparable { /** * @param object $object * @return numeric negative value if $this < $object, positive if $this > $object, 0 otherwise (if objects are considered equal) * @throws ComparatorException if objects are not comparable to each other */ public function compareTo($object); }
interface Comparator { /** * @param object $object1 * @param object $object2 * @return numeric Negative value if $object1 < $object2, positive if $object1 > $object2, 0 otherwise * @throws ComparatorException if objects are not comparable to each other */ public function compare($object1, $object2); }
CSV-Verarbeitung in Magento
Ein Grundsatz bei der Entwicklung, nicht nur mit Magento, ist dass man nicht versuchen sollte, das Rad neu zu erfinden und insbesondere auf die Funktionen des verwendeten Frameworks zurückzugreifen, soweit möglich. Magento hat viele mehr oder weniger bekannte universelle Helfer, in den Helper-Klassen aus Mage_Core sowie unter lib/Varien, und natürlich im Zend Framework.
Ein Klassiker ist z.B. JSON Kodierung. PHP hat zwar built-in die Funktionen json_encode und json_decode, die haben aber einige Unzulänglichkeiten, die in der Implementierung von Zend_Json ausgebügelt wurden. So gibt es in Zend_Json::encode()
einen Zyklen-Check. Magento hat in Mage_Core_Helper_Data::jsonEncode()
noch Support für Inline-Translations innerhalb von JSON hinzugefügt.
In Magento sollte man also immer Mage::helper('core')->jsonEncode()
(bzw. jsonDecode) benutzen.
Varien_File_Csv
Und wie sieht es bei der Verarbeitung von CSV Dateien aus? Da der import und Export im Standard mit CSV Dateien funktioniert, sollte Magento doch etwas haben… Vorhang auf für Varien_File_Csv
. Naja, ich nehme das Ergebnis mal vorweg: außer bei ganz einfachen Aufgaben mit kleinen Dateien ist die Klasse nicht zu gebrauchen.
Ein JSON-RPC Adapter für die Magento API
Beim Durchsehen meiner alten Antworten auf Magento StackExchange bin ich auf diese Frage zum Ansprechen der Magento API via JavaScript gestoßen und musste feststellen dass der Link auf GitHub, der einen wesentlichen Teil der Lösung enthielt, nämlich die Implementierung eines JSON-RPC Adapters für die Magento-API mittlerweile tot ist.
Also habe ich kurzerhand das komplette daraus entstandene Modul selbst veröffentlicht (der originale Link war ein Core Hack):
Das ganze Modul sind weniger als 100 Zeilen Code. In config.xml
wird unser Controller der api
Route hinzugefügt:
<frontend> <routers> <api> <args> <modules> <sgh_jsonrpc before="Mage_Api">SGH_JsonRpc_Api</sgh_jsonrpc> </modules> </args> </api> </routers> </frontend>
Der neue API Adapter wird in api.xml
definiert:
Spryker vs. Magento
Neulich hatte ich die Gelegenheit, einen Blick in den Source Code von Spryker zu werfen, dem Ecommerce-Framework das sich anschickt zum neuen Player im Enterprise-Bereich zu sein. Spryker wird vom Berliner Inkubator Project A für den Einsatz in selbst geförderten Unternehmen entwickelt und soll in diesem Jahr der Öffentlichkeit zugänglich gemacht werden. Wobei Öffentlichkeit nicht ganz stimmt, denn soviel vorab: Eine Open Source Version ist nicht geplant, Lizenzen sollen um 100.000 € / Jahr kosten. Agenturen können sich als Partner registrieren, um ohne Lizenz Zugriff auf Source Code und Dokumentation zu bekommen. Mit der ersten verkauften Lizenz gibt es Zugriff auf zusätzliches Training-Material. Freelancer werden nicht angesprochen. Bereits offiziell als Partner gelistet sind auch die im deutschen Magento-Umfeld bekannten Agenturen CommercePlus und Symmetrics.
Was ist das Besondere an Spryker?
Spryker versteht sich nicht als fertig einsetzbares Produkt, sondern als Framework das alle Bausteine für eine individuelle E-Commerce Lösung bereitstellt, aus denen man sich für sein Projekt die benötigten auswählt und erweitert. Damit wird die Realität berücksichtigt, dass kein Projekt wie das andere ist und jeder Shop seine eigenen Prozesse und Infrastruktur hat, auf die individuell eingegangen werden muss.
Der Kern von Sprkyer sind zwei eigenständige Applikationen, Yves und Zed. Kurz gefasst, ist Yves eine leichtgewichtige Anwendung für das Frontend, Zed das schwere Geschütz fürs Backend.
Yves (in der ersten Version mit Yii programmiert, jetzt mit Silex) liest sämtliche benötigten Daten ausschließlich aus einem In-Memory NoSQL Backend wie Redis.
Zed (Zend Framework 2) übernimmt die Kommunikation mit MySQL, Message Queue und Dritt-Systemen und enthält die Geschäftslogik zu Bestellprozessen usw.
Continue reading “Spryker vs. Magento”
Magento: Block-Inhalt verschwindet nach core_block_to_html_after Event
Vorsicht mit Mage_Core_Block_Abstract::toHtml()
innerhalb eines Observers für core_block_to_html_after
! Ich habe die Methode genutzt, um HTML aus einem Block in einen existierenden Block zu injizieren, mit dem Ergebnis dass alles außer diesem neuen Block von der Ausgabe entfernt wurde.
Beim Debugging im Core habe ich die Ursache darin gefunden, wie das Event dispatched wird:
/** * Use single transport object instance for all blocks */ if (self::$_transportObject === null) { self::$_transportObject = new Varien_Object; } self::$_transportObject->setHtml($html); Mage::dispatchEvent('core_block_abstract_to_html_after', array('block' => $this, 'transport' => self::$_transportObject)); $html = self::$_transportObject->getHtml();
Wie man sieht, ist das Transport-Objekt, das genutzt wird um Änderungen am HTML in Observern zu ermöglichen, eine Klassenvariable von Mage_Core_Block_Abstract
, und verhält sich ähnlich wie ein Singleton. Ich kann mir keinen guten Grund dafür denken aber es riecht verdächtig nach premature optimization.
Was nun passiert ist, dass während das Event verarbeitet wird, der neue Block seine eigene Ausgabe in seinem eigenen toHtml()
Aufruf dem selben Transport-Objekt zuweist und die ursprüngliche Ausgabe verloren geht, wenn man sie nicht vorher gesichert hat.
Die Lösung für mein konkretes Problem war, den Block an anderer Stelle zu erstellen und vorzurendern, aber wenn das nicht getan wird, muss die Ausgabe direkt zu Beginn im Observer in eine neue Variable kopiert werden:
$html = $observer->getTransport()->getHtml(); // should be the first statement // now you can do what you want, create other blocks, modifiy $html ... $observer->getTransport()->setHtml($html); // should be the last statement