Magento: Eine eigene Extension erstellen

Abb. 1: Der Gesamtpfad zur neu anzulegenden Extension.

Abb. 2: Im Backend zunächst den Cache löschen.
Extensions (dt. "Erweiterungen") sind der Weg der Wahl, um die Funktionsweise des Shopsystems Magento grundlegend zu beeinflussen und den Umfang an Features entscheidend zu erweitern. Von Haus aus bringt Magento schon eine Menge an Leistungsfähigkeit mit; als Entwicklung eines US-Unternehmens vermisst man aber z. B. für den Einsatz im deutschsprachigen Bereich wichtige Merkmale wie etwa die Abwicklung von Lastschriften oder das dynamische Ändern von Versandkosten abhängig von der Zahlungsweise (Nachnahmeaufschlag!). Auch kann es notwendig werden, Preise beim Hinzufügen in den Warenkorb noch nachzumodifizieren, etwa dann, wenn ein Artikel Aufschläge für Sonderanfertigungen hat, dieser Aufschlag aber nur einmal, unabhängig von der Anzahl bestellter Artikel dieser Art, berechnet wird. Für alle diese Zwecke füllen Extensions die Lücke aus, die der Hersteller in dieser Hinsicht gelassen hat.
Die Einsatzmöglichkeiten von Extensions sind also mannigfaltig. Sie können sowohl standardmäßige Magento-Funktionalitäten überschreiben und erweitern, so dass statt der ursprünglichen Klassen samt deren Attributen und Methoden primär jene der Extension verwendet werden, als auch auf bestimmte Ereignisse "lauschen" (wie etwa das Befüllen des Warenkorbs, dessen Löschung, den Bestellabschluss etc.) und sich im Fall, dass diese Ereignisse eintreten, mit ihrer eigenen Funktionalität dazwischenschalten. Wie bestimmte Probleme auf Basis von Extensions, Event-Listenern und vererbten Klassen gelöst werden können, wird in weiteren Informationstexten hier auf kotori.de detailliert und unter Voraussetzung der Kenntnis grundlegender Begriffe der objektorientierten Programmierung sowie des MVC-Prinzips besprochen. An dieser Stelle sei nur zusammengefasst, welche Schritte nötig sind, um eine eigene rudimentäre Extension zu erstellen.
Magento sucht nach Extensions innerhalb von zwei festgelegten Pfaden: einerseits
/app/code/local, andererseits
/app/code/community. Konventionellerweise wählt man
local für Extensions, die nur für den örtlichen Einsatz auf einem System entwickelt sind und
community für zur Weitergabe bestimmte Extensions. Beim Durchlaufen der Verzeichnisse wird
local vor
community stets bevorzugt. Wir entscheiden uns hier für
local und legen für alle unsere künftigen Extensions dort ein Sammelverzeichnis (entweder per Shell oder FTP-Zugriff) an; nennen wir es "Kotori". Der Name der Extension wird durch Einrichten eines weiteren Verzeichnisses dort festgelegt als "Myextension", somit ergibt sich als Gesamtpfad zur Extension
/app/code/local/Kotori/Myextension (Abb. 1).
Im Extension-Verzeichnis ist nun als absolutes Minimum das Verzeichnis
etc anzulegen, das die Konfigurationsdatei
config.xml beherbergt. Diese Datei dient zunächst nur ganz fundamental zum Anmelden der Extension im System und hat die folgende Struktur:
01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| <?xml version="1.0"?>
<config>
<modules>
<Kotori_Myextension>
<version>0.1.0</version>
</Kotori_Myextension>
</modules>
<global>
<blocks>
</blocks>
<models>
</models>
<events>
</events>
</global>
<frontend>
<routers>
</routers>
</frontend>
<default>
</default>
</config> |
Ist diese Datei angelegt, wechseln wir in das Verzeichnis
/app/etc/modules. Auch hier ist eine XML-Datei zu erstellen. In diesem Fall heißt sie ganz einfach Kotori_Myextension.xml und sieht so aus (wäre unsere Extension unter
/app/code/community abgelegt, würde zwischen den
codePool-Tags entsprechend auch eine andere Pfadangabe stehen):
1: 2: 3: 4: 5: 6: 7: 8: 9:
| <?xml version="1.0"?>
<config>
<modules>
<Kotori_Myextension>
<active>true</active>
<codePool>local</codePool>
</Kotori_Myextension>
</modules>
</config> |

Abb. 3: Alles in Ordnung - unsere Extension wurde erfolgreich registriert.
Nun schauen wir nach, ob Magento die neue Extension bereits registriert hat. Nach einem Login im Administrationsbackend wird zunächst der Cache gelöscht (zu finden unter
System | Cache Management, Abb. 2). Dann wechseln wir über
System | Configuration in den Konfigurationsschirm und wählen aus der Rubrik
Advanced ebenso den Menüpunkt
Advanced. Dort gibt es nur eine Konfigurationsmöglichkeit, nämlich das Ein- und Ausschalten einzelner Module, die Magento bereits bekannt sind. Die meisten davon bringt das System bereits mit (erkennbar am Präfix
Mage), allerdings sollte jetzt auch unsere
Myextension in der Liste auftauchen (Abb. 3). Da Magento sie erfolgreich registriert hat, können wir uns jetzt einer grundlegenden Funktionalität zuwenden. Diese soll nur daraus bestehen, im bereits vorhandenen Layout des Shops einen "Hallo Welt"-Text darzustellen.
Damit unsere Extension Seitenaufrufe per URL in Funktionsaufrufe umsetzen kann, müssen wir ihr einen eigenen Controller hinzufügen. Dazu erstellen wir das Verzeichnis
/app/code/local/Kotori/Myextension/controllers und legen darin eine Datei
DisplayController.php an. Diese Klasse erweitert die Klasse
Mage_Core_Controller_Front_Action und trägt selbst die Bezeichnung
Kotori_Myextension_DisplayController.
01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17:
| <?php
class Kotori_Myextension_DisplayController extends Mage_Core_Controller_Front_Action
{
public function indexAction()
{
$this->loadLayout();
$this->getLayout()
->getBlock('root')
->setTemplate("page/1column.phtml");
$this->getLayout()
->getBlock('content')->append(
$this->getLayout()->createBlock('myextension/index') );
$this->renderLayout();
}
} |
Die Spezifikation der Controller-Klasse reicht allerdings noch nicht aus. In der Datei
/app/code/local/Kotori/Myextension/etc/config.xml sind noch speziell innerhalb des
<frontend>-Tags diese Veränderungen vorzunehmen:
01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| <?xml version="1.0"?>
<config>
<modules>
<Kotori_Myextension>
<version>0.1.0</version>
</Kotori_Myextension>
</modules>
<global>
<blocks>
</blocks>
<models>
</models>
<events>
</events>
</global>
<frontend>
<routers>
<Kotori_Myextension>
<use>standard</use>
<args>
<module>Kotori_Myextension</module>
<frontName>myextension</frontName>
</args>
</Kotori_Myextension>
</routers>
</frontend>
<default>
</default>
</config> |

Abb. 4: Die Extension liefert eine Seite aus, aber noch ohne Inhalt.
Entsprechend dieser Konfiguration erreichen wir die
indexAction()-Funktion aus der Controller-Klasse nun unter dem URL
http://(URL des Shops)/myextension/display/index. Die Seite wird gefunden und das Layout auch ausgeliefert; ein Inhalt ist jedoch noch nicht hinterlegt. Dies geschieht erst mittels einer Block-Definition.
Dazu ist das Verzeichnis
/app/code/local/Kotori/Myextension/Block zu erstellen; darin deponieren wir eine Klasse mit dem Bezeichner
Kotori_Myextension_Block_Index und dem Dateinamen
Index.php. Sie hat diese Struktur:
1: 2: 3: 4: 5: 6: 7: 8:
| <?php
class Kotori_Myextension_Block_Index extends Mage_Core_Block_Template
{
protected function _toHtml()
{
return 'Hallo Welt!';
}
} |
Und schließlich muss auch
/app/code/local/Kotori/Myextension/etc/config.xml noch einmal innerhalb der
<blocks>-Tags erweitert werden, damit die obige Blockklasse von der
createBlock()-Methode im Controller richtig zugeordnet werden kann:
01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| <?xml version="1.0"?>
<config>
<modules>
<Kotori_Myextension>
<version>0.1.0</version>
</Kotori_Myextension>
</modules>
<global>
<blocks>
<myextension>
<class>Kotori_Myextension_Block</class>
</myextension>
</blocks>
<models>
</models>
<events>
</events>
</global>
<frontend>
<routers>
<Kotori_Myextension>
<use>standard</use>
<args>
<module>Kotori_Myextension</module>
<frontName>myextension</frontName>
</args>
</Kotori_Myextension>
</routers>
</frontend>
<default>
</default>
</config> |

Abb. 5: Der Block mit unserem "Hallo Welt"-Text wird jetzt richtig ausgeliefert.
Rufen wir
http://(URL des Shops)/myextension/display/index jetzt noch einmal auf. Der als Rückgabewert der
_toHtml()-Methode in der Blockklasse spezifizierte "Hallo Welt"-Text wird jetzt durch den Controller als Seiteninhalt korrekt dargestellt (Abb. 5).
Analog können nun auch im Controller beliebige weitere über den URL ansprechbare Methoden definiert werden.