Auf Bestellungen reagieren / Event-Observer



Wenn Sie mit einer WaWi(Warenwirtschaft) arbeiten, möchten Sie sicherlich die Auftragsdaten auch in Ihre WaWi importieren/einspielen. Wenn möglich sollten die Daten in Realtime, als sobald eine Bestellung erfolgt übertragen werden. Man könnte nun die dafür zuständige Klasse überschreiben - an dieser Stelle möchte ich aber zeigen, dass es auch noch eine andere Möglichkeit gibt. Magento löst bei bestimmten Aktionen sogenannte Events/Ereignisse aus. Diese kann man abfragen und eigene Funktionen hinterlegen.

Aber - man muss dafür ein eigenes Modul erstellen. Wie immer beim Erstellen eines Magento-Moduls, befindet sich die Basisdefintion in der config.xml.

<config>
...
  <frontend>
    <events>
      <EVENT>
        <observers>
          <bezeichnung>
            <type>singleton></type>
            <class>model/observer</class>
            <method>funktionsname</method>
          </bezeichnung>
        </observers>
      </EVENT>
    </events>
  </frontend>
...
</config>

Bei EVENTS muss ein Ereignis eingetragen werden, welches man überwachen und auswerten möchten. In meinem Fall verwende ich das Ereignis checkout_onepage_controller_success_action, welches bei Neubestellungen im Frontend ausgelöst wird. Wie Sebastian (unten in den Kommentaren) angeregt hat kann man alternativ auch die Ereignissse checkout_type_onepage_save_order_after oder sales_order_save_after verwenden.

Branko Ajzele hat eine Übersicht aller Events von Magento 1.3.0 erstellt - es lohnt sich diese genauser anzusehen.
Die Bezeichnung kann frei gewählt werden. Der Typ kann model oder singelton sein. Bei einem Model-Observer wird vor jedem Aufruf der Methode eine neue Instanz des Observers erstellt, wobei bei einem Singelton-Observer nur eine Instanz erstellt wird. Die Klassendefintion (class) beinhaltet die Model-Defintionen mit der dazugehörenden PHP-Datei. Die Defintion des aufzurufenden Methode erklärt sich ja von selbst.

Nach dieser trockenen Theorie wollen wir uns doch gleich an ein praktisches Beispiel wagen. Mit meiner Erweiterung möchte ich nach einem erfolgreichen Bestellprozess die Bestelldaten auslesen und als Datei abspeichern. Sie haben nach Fertigstellung dieses Tutorials ein komplettes Grundgerüst für die Verarbeitung von Bestelldaten nach dem Absenden eines neuen Auftrages im Onlineshop.

Umsetzung

1. app/etx/modules/Mxperts_CheckoutSuccess.xml

<?xml version="1.0"?>
<config>
  <modules>
    <Mxperts_CheckoutSuccess>
      <active>true</active>
      <codePool>local</codePool>
    </Mxperts_CheckoutSuccess>
  </modules>
</config>

Als erstes müssen wir unsere Erweiterung bei Magento registrieren. Dies erfolgt mit der oben aufgeführen Datei. Links finden Sie den kompletten Verzeichnisbaum, der für dieses Tutorial benötigt wird. Ich füge diese Erweiterung wieder in unsere Mxperts-Serie ein. Falls Sie Fragen zur Programmierung von Extensions haben, möchte ich sie an dieser Stelle auf unsere Reihe Extension Tutorial Teil1-Teil10 verweisen.

2. app/code/local/Mxperts/CheckoutSuccess/etc/config.xml

<?xml version="1.0" encoding="UTF-8"?>
<config> 

  <modules>
    <Mxperts_CheckoutSuccess>
        <version>1.0.0</version>
    </Mxperts_CheckoutSuccess>
  </modules>  

  <global>
    <models>
      <checkoutsuccess>
        <class>Mxperts_CheckoutSuccess_Model</class>
      </checkoutsuccess>
    </models>
  </global>  

  <frontend>
    <events>
      <checkout_onepage_controller_success_action>
        <observers>
	  <beliebige_bezeichnung>
            <type>singleton</type>
            <class>checkoutsuccess/observer</class>
            <method>meine_funktion</method>
          </beliebige_bezeichnung>
        </observers>
      </checkout_onepage_controller_success_action>
    </events>
  </frontend>    

</config>

Der Aufbau der Datei erfolgt wie bereits weiter oben beschrieben. In einigen Beispielen im Magento-Forum hat die Models-Defintion gefehlt. Dies führte zwangsläufig zu Fehlermeldungen, da Magento die PHP-Datei dann im Core sucht.
Wenn wir die Models-Defintion weglassen, erhält man folgende Fehlermeldung:

Warning: include(Mage/Checkoutsuccess/Model/Observer.php) [function.include]: failed to open stream: No such file or directory  in /var/www/vhosts/mxperts.de/subdomains/shop/httpdocs/app/code/core/Mage/Core/functions.php on line 70
Trace:
#0 /var/www/vhosts/mxperts.de/subdomains/shop/httpdocs/app/code/core/Mage/Core/functions.php(70): mageCoreErrorHandler(2, 'include(Mage/Ch...', '/var/www/vhosts...', 70, Array)
#1 /var/www/vhosts/mxperts.de/subdomains/shop/httpdocs/app/code/core/Mage/Core/functions.php(70): __autoload()
#2 [internal function]: __autoload('Mage_Checkoutsu...')
...

3. app\code\local\Mxperts\CheckoutSuccess\Model\Observer.php

<?php
  class Mxperts_CheckoutSuccess_Model_Observer extends Mage_Core_Model_Abstract { 

    public function __construct()
    {
        $fp = fopen('obs_created.txt','w+');
        fwrite($fp, "Objekt Mxperts_CheckoutSuccess_Model_Observer erstellt!! ".date("Y-m-d H:i:s")."\n");
        fclose($fp);
    }

    public function meine_funktion($observer)
    {
        $event = $observer->getEvent();
//        !-fehlercode!();
        $fp = fopen('obs_order.txt','w+');
        fwrite($fp, "------------[Neuer Auftrag]-----------------\n");

        $orderId = Mage::getSingleton('checkout/type_onepage')->getCheckout()->getLastOrderId();
        $order = Mage::getModel('sales/order')->load($orderId);
        $items = $order->getAllItems();

        fwrite($fp, "\n".'$event ='."\n");
        fwrite($fp, print_r($event, true) );

        fwrite($fp, "\n".'$order ='."\n");
        fwrite($fp, print_r($order, true) );

        fwrite($fp, "\n".'$items ='."\n");
        fwrite($fp, print_r($items, true) );                

        fwrite($fp, "\n".'$_SESSION ='."\n");
        fwrite($fp, print_r($_SESSION, true) );

        fclose($fp);
    }

  }
?>

Nachdem wir unsere Klasse definiert haben, muss nur noch der Cache aktualisiert werden. Erstellen Sie in Ihrem Magento-Shop nun einen neuen Auftrag. Danach sollten sich im Root-Verzeichnis die beiden Datein obs_created.txt und obs_ordered.txt mit entsprechenden Daten befinden. Falls Sie kein Ergebnis bekommen, entfernen Sie den Kommentar bei !-fehlercode!();. Bei nochmaliger Bestellung sollten Sie einen Fehler erhalten. Its dies nicht der Falls kontrollieren Sie nochmals Ihre config.xml.

WICHTIG: Löscht nach der Testphase die erzeugten Textdatein, da sich darin auch Daten aus der Konfiguration von Magento befinden!

Nun können Sie die Funktion mit vernünftigem Inhalte füllen. In unserem Falls ist das eine spezielle Formatierung und die Weiterleitung an eine Warenwirtschaft.

Download aller Dateien: event_observer.zip

Viele Grüße
Johannes Teitge

  • Twitter
  • Webnews
  • Mister-Wong
  • Facebook
  • Digg
  • BlogMarks
  • Share/Save/Bookmark

9 Kommentare to “Auf Bestellungen reagieren / Event-Observer”

  1. Sebastian Sebastian sagt:

    Hi Johannes,

    meiner Meinungn ach wäre es eleganter auf das Event checkout_type_onepage_save_order_after (oder allgemein sales_order_save_after) zu warten - so umgeht man das nachträgliche Laden der Bestellung. Außerdem deckt dein Event nur eine Bestellung im Frontend ab - ist eben nur der controller der im Frontend aufgerufen wird wenn eine Bestellung aufgegeben wird - nicht aber im Backend.

    Ansonsten nett geschrieben, wie eigentlich alles hier. :-)

    Viele Grüße
    Sebastian

    • Hallo Sebastian,

      vielen Dank für den Tipp - in meinem Fall sollen eben nur die Bestellungen im Frontend abgedeckt werden. Aber für andere User sicherlich ein wichtiger Hinweis.
      Um aber auf Bestellungen im Backend reagieren zu können musst du in der config.xml die entsprechende Defintion machen.
      <backend>
        <events>

      Und vielen Dank auch für das Lob.

      Viele Grüße
      Johannes Teitge

  2. Wenn man nur Bestellungen behandeln möchte, die auch bezahlt wurden, dann kann man das Event “sales_order_invoice_pay” nutzen. Ansonsten würden auch unbezahlte Bestellungen per Vorkasse verarbeitet, was man ja eventuell nicht möchte.

    • Stimmt, da hast Du sicherlich recht - es kommt eben immer auf die Anforderungen an. In meinem Fall benutzt der Kunde das Backend überhaupt nicht. Weder für das Bearbeiten der Produkte noch für die Auftragsbearbeitung. D.h. die Befüllung des Shops läuft voll automatisiert ab und die Aufträge werden sofort an die WaWi übergeben. In der WaWi findet die weitere Verarbeitung statt.

      Viele Grüße
      Johannes Teitge

  3.  takatiki sagt:

    Hallo zusammen,

    wie müsste es denn aussehen wenn ich einen Observer im Admin überschreiben möchte, hier konkret wenn ein Artikel gespeichert wird. Ich habe es anstatt mit probiert komme aber nicht weiter. Der Event lautet catalog_product_prepare_save. Danke im voraus

  4.  marwestermann sagt:

    Hi,

    finde das tutorial super, hab ich auch ohne Probleme hinbekommen. Hab nur ne Frage, anmerkung dazu.

    Mage::getSingleton(’checkout/type_onepage’)->getCheckout()->getLastOrderId();

    ist gewährleistet, dass es wirklich die richtige Order-ID ist? Was passiert, wenn 2 User quasi gleichzeitig auf checkout klicken. kann es nicht passieren, dass dann zweimal die gleiche (letzte) order-id zurückkommt?

    • Dafür gibt es dann das Session-Management - also sollte es da keine Probleme geben.

      Wenn man sich das im Code anschaut:

      Die Funktion getLastOrderId() befindet sich in der Klasse Mage_Checkout_Model_Type_Onepage. Der Aufruf sieht wie folgt aus:
      $order = Mage::getModel('sales/order');
      $order->load($this->getCheckout()->getLastOrderId());
      $orderId = $order->getIncrementId();
      return $orderId;

      Die Funktion getCheckout() wiederum, interagiert mit checkout/session.
      public function getCheckout()
      {
      return Mage::getSingleton('checkout/session');
      }

      Grüße
      Johannes Teitge

  5.  nikl sagt:

    Danke, wie immer super! Die Tatsache, dass es, bis die Dateien erstellt wurden, mehrere Minuten dauerte, zeigt mir jetzt auch deutlich, dass es Zeit für einen ManagedServer wird…

Kommentar erstellen

You must be logged in to post a comment.

Bitte beachten: Mxperts.de ist kein Supportforum sondern eine Informationsplattform, deshalb benutzt für Diskussionen das deutsche Forum von Magento. (Fragen/Kommentare zu den Tutorials ausgeschlossen). Außerdem gebe ich keinen kostenlosen Support zu Magento. Leider haben das einige Leser in letzter Zeit falsch Verstanden und ich bitte um Euer Verständnis. Ich denke diese Plattform ist von unserer Seite aus schon genügend Gratis-Leistung.