finishAction() übersichtlich erweitern

Hallo,

Ich bin auf der Suche, wie man eine bereits existierende action (genauer gesagt die finishAction im Checkout Controller) erweiter kann, ohne dabei die komplette Checkout.php aus dem Controllers/Frontend Ordner in das eigene Plug-In kopieren zu müssen, da das ja nicht wirklich updatefreundlich ist, schätz ich mal.

Ich habe auf der Suche dann diesen Foreneintrag gefunden: https://forum.shopware.com/discussion/34252/controller-action-ueberschreiben-erweitern

Allerdings ist hier die Rede von Hooks und bisher habe ich zum Thema Hooks nur gelesen, dass man die Finger davon lassen soll, weil bad practice. Ich schätze also mal, dass es hier eine schönere Lösung gibt.

 

Um das ganze ein weniger konkret zu machen hier ein paar genauere Infos:

In meiner Bootstrap.php gibt es eine Funktion die generateCode heißt. Diese erstellt eine Zeichenfolge folgendermaßen:

    public function generateCode()
    {
      //Creates 16 times a number and add it to the var
        $rand = 0;
        for ($i = 0; $i<15; $i++)
            {
                $rand .= mt_rand(0,9);
            }
            //On Checkoutcomplete add that random number to database table
        $addInt = "INSERT INTO `s_plugin_tnev` (`vouchercode`) VALUES ($rand);";
        $connect = Shopware()->Db()->query($addInt);
    }

Diese Funktion soll nun ausgelöst werden, wenn der Kunde eine Bestellung erfolgreich abgeschlossen hat. Das würde ja heißen, wenn der Kunde die URL: webauftritt.de/frontend/checkout/finish erreicht hat wird diese Funktion ausgelöst.

Wenn ich nun diesen Code genau so in die Checkout.php reinkopier, funktioniert das auch einwandfrei. Nur möchte ich das etwas übersichtlicher.

Die finishAction()-Funktion ist in der Checkout.php sehr sehr lang. Ich suche also nach so etwas ungefähr:

class Shopware_Controllers_Frontend_CheckoutGenerate extends Shopware_Controllers_Frontend_Checkout
{
     function finishAction()
      {
          generateCode();
          parent::finishAction();
      };
};

Nur leider funktioniert das nicht.

Gibt es hierfür irgendeine schöne Lösung die mit Shopware kompatibel ist? :slight_smile:

Mein Plugin-Verzeichnis teilt sich folgendermaßen auf:

  • Frontend
    • meinPlugin
      • Bootstrap.php
      • Controllers
        • Frontend
          • Checkout.php

Beste Grüße,

Max Konrad

Hier im Forum fand ich die Methode:

 Shopware\_Controllers\_Frontend\_Checkout::finishAction::before

In meine Falle machte sie genau das was ich wollte.

@IFF schrieb:

Hier im Forum fand ich die Methode:

Shopware_Controllers_Frontend_Checkout::finishAction::before

Hmm schade. Das wäre ja dann der in der documentation beschriebene Hook von dem fast immer abgeraten wird.

Hallo Max,

zur Erweiterung von Shopware solltest du immer Events benutzen. Hooks sind, wie du schon richtigerweise herausgefunden hast, eher nicht die richtige Wahl.
Um nun etwas nach/während der finishAction auszuführen hast du mehrere Möglichkeiten:

Auf das Event ‘Enlight_Controller_Action_PostDispatchSecure_Frontend_Checkout’ subscriben. Damit dein Code auch wirklich nur auf der finishAction ausgeführt wird, musst du allerdings auf den action-Namen in der Callback Methode prüfen.

public function onPostDispatchCheckout(\Enlight_Controller_ActionEventArgs $args)
{
    /** @var \Enlight_Controller_Action $controller */
    $controller = $args->getSubject();

    /** @var \Enlight_Controller_Request_Request $request */
    $request = $controller->Request();

    if ($request->getActionName() !== 'finish') {
        return;
    }

    // do your stuff here
}

Alternativ nutzt du ein Event, dass während des Speicherns der Bestellung geworfen wird. Hier findest du in der \sOrder::sSaveOrder() Methode einige Stellen. 

Viele Grüße aus Schöppingen

cool Michael Telgmann

4 „Gefällt mir“

Hier irgendwo im Forum wurde er von Shopware empfohlen.

@Michael Telgmann schrieb:

Hallo Max,

zur Erweiterung von Shopware solltest du immer Events benutzen. Hooks sind, wie du schon richtigerweise herausgefunden hast, eher nicht die richtige Wahl.
Um nun etwas nach/während der finishAction auszuführen hast du mehrere Möglichkeiten:

Auf das Event ‚Enlight_Controller_Action_PostDispatchSecure_Frontend_Checkout‘ subscriben. Damit dein Code auch wirklich nur auf der finishAction ausgeführt wird, musst du allerdings auf den action-Namen in der Callback Methode prüfen.

public function onPostDispatchCheckout(\Enlight_Controller_ActionEventArgs $args)
{
/** @var \Enlight_Controller_Action $controller */
$controller = $args->getSubject();

/** @var \Enlight_Controller_Request_Request $request */
$request = $controller->Request();

if ($request->getActionName() !== ‚finish‘) {
return;
}

// do your stuff here
}

Alternativ nutzt du ein Event, dass während des Speicherns der Bestellung geworfen wird. Hier findest du in der \sOrder::sSaveOrder() Methode einige Stellen. 

Viele Grüße aus Schöppingen

cool Michael Telgmann

Super. Vielen Dank für die übersichtliche Antwort. Würde das dann alles in meine Bootstrap.php Datei kommen oder sollte das ausgelagert werde?

Nutzt du das alte oder das neue Plugin-System? 
Grundsätzlich sollte die Basisklasse deines Plugins nicht zu voll werden. Einfach der Übersichtlichkeit wegen. Wenn das Plugin aber nur das machen soll, was du oben beschrieben hast, dann ist es völlig i.O. alles in der Basisklasse zu bauen.

Viele Grüße aus Schöppingen

cool Michael Telgmann

Momentan benutze ich noch das alte Shopware Plugin System. Es kommt schon noch ein bisschen was dazu, aber mir ging es viel mehr darum, ob Shopware diese Methode in einem bestimmten Ordner oder so sucht und braucht. Aber aus der Antwort schließe ich mal, dass die Methode einfach im Main Directory sein kann.