Hallo Welt, ich versuche eine Bestandsprüfung in Laufzeit via Import zu bauen, die dann als Teil eines Modules/Plugins laufen soll. Vor Abschluss jeder Bestellung, sollen alle Artikel im Warenkorb/Kasse nochmal auf ihren Bestand geprüft werden, dazu will ich einen Import die Bestandmengen der ausgewählten Artikel durch den Logistikpartner einholen. Bei Bestand > AnzahlBestellung, soll die Bestellung normal gespeichert und dem Logistikpartner via Export eine Bestellung übermittelt werden. Bei Bestand < AnzahlBestellung, müsste eine Fehlermeldung erscheinen oder ggf. sogar die Bestellung abgebrochen werden. Für dieses Szenario habe ich an Hooks gedacht: <?php class Shopware_Plugins_Backend_TestApi_Bootstrap extends Shopware_Components_Plugin_Bootstrap
{
public function install()
{
$event = $this->createHook( 'sOrder', 'sSaveOrder', 'onOrder', Enlight\_Hook\_HookHandler::TypeBefore, 0 ); $this-\>subscribeHook($event); return true; } static function onOrder (Enlight\_Event\_EventArgs $args) { if($order-\>article[0] \< $blub) //wie komme ich hier an die Artikel der Bestellung heran? { //... } } }
Ich denke im install()-Part baue ich den Hook etwa so ein. TypeBefore erzielt hoffentlich seine Wirkung, also springt vor dem Speichern der Bestellung ein. Korrekt? (Hab in meinem Leben och nie mit hooks gearbeitet.) Im onOrder-Part muss ich nun die Bestellartikel (bzw. die jeweiligen ordernumber) und die Bestellanzahl auslesen (um dann meinen SOAP-Request/Response auszuführen). Aber wie frage ich die Artikel+Bestellmengen einer noch nicht gespeicherten Bestellung ab? Ich bin für jeden Hinweis dankbar.
In $args müssten ja die Artikel der Bestellung und deren Bestellmengen drinstecken, oder?
ich würde erstmal den Warenkorb mit $basket = Shopware()-\>Modules()-\>Basket()-\>sGetBasket();
laden, und auf die Datenstruktur kann man z.B. mit $ob\_attr1 = $basket['content']['0']['ob\_attr1'];
zugreifen. In deinem Fall wirst du $basket einmal durchiterieren um für jeden Artikel die Verfügbarkeit zu prüfen.
Ich wollte jetzt schon $args durchforsten, aber das ist protected und teilweise private Aber ich versuch’s mal via Shopware()->Modules()->Basket()->sGetBasket() Soweit erstmal vielen herzlichen Dank. Ich schau mal, wie weit ich komme und lass das Thema erstmal noch offen.
Also gut, das funktioniert. [code]<?php class Shopware_Plugins_Backend_TestApi_Bootstrap extends Shopware_Components_Plugin_Bootstrap
{
public function install()
{
$event = $this->createHook( ‘sOrder’, ‘sSaveOrder’, ‘onOrder’, Enlight_Hook_HookHandler::TypeBefore, 0 ); $this->subscribeHook($event); return true; } static function onOrder(Enlight_Event_EventArgs $args) { echo ’
‘; $basket = Shopware()->Modules()->Basket()->sGetBasket(); foreach($basket[‘content’] as $basketArticle) { echo $basketArticle[‘ordernumber’].’:’.$basketArticle[‘quantity’]."
"; } echo ’
'; } }[/code] [color=gray]Aber gibt es eine Möglichkeit die Bestellung abzubrechen? Also Nicht etwa mit einem PHP-Ausstieg, wie exit() oder die(). Ich suche nach einer Methode, um den Bestellvorgang nicht zu beenden, sondern vorzeitig zum Scheitern zu bringen.[/color] Noch eleganter wäre ein Hinweis, noch während der Bestätigung/Bestellzusammenfassung. Komme ich da mit einem HookHandler irgendwie dazwischen? Das wäre dann diese Seite: [color=blue]/shopware.php/sViewport,checkout/sAction,confirm[/color] (bzw. /success,payment), aber wie spreche ich Methode (2. Hook-Parameter) an? Bzw. Wie heißt diese Methode überhaupt? Die Objektklasse (1. Hook-Parameter) bleibt ja sicherlich “sOrder”. Nur der Methodenname ist mir nicht bekannt. Dort würde ich dem Käufer gerne die Möglichkeit geben auszuwählen, ob er die “nicht-lagernden Artikel” wieder rauswerfen oder sonst auf längere Lieferzeiten eingehen möchte.
Okay, hab jetzt diese Lösung. Aber sobald ich F5 drücke, wird die Methode nimmer ausgeführt. [code]<?php class Shopware_Plugins_Backend_TestApi_Bootstrap extends Shopware_Components_Plugin_Bootstrap
{
public function install()
{
$event = $this->createHook( ‘sBasket’, ‘sGetBasket’, ‘onOrder’, Enlight_Hook_HookHandler::TypeBefore, 0 ); $this->subscribeHook($event); return true; } static function onOrder(Enlight_Event_EventArgs args) { if(_GET[‘sAction’] == ‘confirm’ && ($GLOBALS[‘doNotRepeat’]++ == 0)) { echo ’
‘; $basket = Shopware()->Modules()->Basket()->sGetBasket(); foreach($basket[‘content’] as $basketArticle) { echo $basketArticle[‘ordernumber’].’:’.$basketArticle[‘quantity’]."
"; if($basketArticle[‘ordernumber’]) { //… } } echo ’
'; } } }[/code] Außerdem findet meine interne Abfrage beim Logistigpartner via SOAP statt. Bei 100 Artikeln im Warenkorb wäre das sehr langsam. Gibt es eine Methode, die ich “hooken” könnte, während ich den Artikel in den Warenkorb lege? Denn dann dauert die Anfrage deutlich unter 1 Sekunde, was notfalls mal verkraftbar wäre.
So, hier nun also mein Warenkorb-Hook: [code]<?php class Shopware_Plugins_Backend_TestApi_Bootstrap extends Shopware_Components_Plugin_Bootstrap
{
public function install()
{
$event = $this->createHook( ‘sBasket’, ‘sAddArticle’, ‘onAddArticle’, Enlight_Hook_HookHandler::TypeBefore, 0 ); $this->subscribeHook($event); return true; } static function onAddArticle(Enlight_Event_EventArgs $args) { if($GLOBALS[‘doNotRepeat’]++ == 0) //just one call { echo ’
‘; if($_GET[‘sAdd’]) { checkArticle['ordernumber'] = _GET[‘sAdd’]; checkArticle['quantity'] = _GET[‘sQuantity’]; if(!$checkArticle[‘quantity’]) { $checkArticle[‘quantity’] = 1; } $basket = Shopware()->Modules()->Basket()->sGetBasket(); foreach($basket[‘content’] as $basketArticle) { if($basketArticle[‘ordernumber’] == $checkArticle[‘ordernumber’]) { $checkArticle[‘quantity’] += $basketArticle[‘quantity’]; } } echo $checkArticle[‘ordernumber’].’:’.$checkArticle[‘quantity’]."
"; //… soap - stockInfo - check } echo ’
'; } } }[/code] Wie kann ich denn eine Methode, also z.B.: $sBasket->sAddArticle() abbrechen? Denn ein return false; wird ja sicherlich ned funktionieren, da ich mich ja in meiner onAddArticle befinde. Gibt es eine Möglichkeit über Type::before einen Ausstieg zu definieren?
Hi, das geht mit folgendem Trick. Als ersten muss man die Methode mit den Hook-Typ “Replace” komplett überschreiben. Danach kann man über “excuteParent” selbst entscheiden, wann (bzw. ob) die originale Methode aufgerufen werden soll: class Shopware\_Plugins\_Backend\_TestApi\_Bootstrap extends Shopware\_Components\_Plugin\_Bootstrap { public function install() { $event = $this-\>createHook( 'sBasket', 'sAddArticle', 'onAddArticle', Enlight\_Hook\_HookHandler::TypeReplace, 0 ); $this-\>subscribeHook($event); return true; } static function onAddArticle(Enlight\_Event\_EventArgs $args) { if (...) { ... } else { $args-\>setReturn($args-\>getSubject()-\>excuteParent( 'onAddArticle', $args-\>getArgs() )); } } }
Heiner
Hallo Heiner, erst mal Danke für den Tipp. Das funktioniert zwar, aber es ist ziemlich langsam. Wenn ich mit … sUpdateArticle($\_GET['sAdd'],$basketArticle['quantity'] - $\_GET['sQuantity'])
… arbeite, ginge es schneller. Außerdem fiel mir auf, dass es wesentlich schneller geht, wenn ich die Hook-Methode „onOrder“, als wenn ich sie „onAddArticle“ nenne. Irre ich mich da möglicherweise? Eigentlich sollte der Name der Methode doch egal sein. Aber das Frontend läd den Warenkorb 3x schneller, wenn die Methode „onOrder“ heißt. Unlogisch oder? Möglicherweise liegt es aber auch am TypeReplace, was anscheinend länger benötigt als TypeBefore. Gibt es die Möglichkeit ein alternatives Template für die Warenkorbausgabe zu laden? Also anstatt: [quote]Der Artikel wurde erfolgreich in den Warenkorb gelegt … [Weitershoppen] [Warenkorb anzeigen] [zur Kasse] … Diese Artikel könnten Ihnen gefallen …[/quote] Eben irgendwas eigenes, wie: [quote]Leider kann dieser Artikel zurzeit nicht bestellt werden. Vorbestellung? [JA] / [NEIN][/quote].