Ich möchte eine Geschäftsansicht programmgesteuert löschen . Betrachtet man Mage_Adminhtml_System_StoreController::deleteStorePostAction()
, ist dies ziemlich einfach (etwas verkürzter Code):
$model = Mage::getModel('core/store')->load($id);
if ($model->getId() && $model->isCanDelete()) {
$model->delete();
Mage::dispatchEvent('store_delete', array('store' => $model));
}
Ich möchte diesen Code in ein Datenaktualisierungsskript einfügen , damit der Löschvorgang automatisch ausgeführt wird.
Das Problem ist, dass während der Ausführung der Upgrade-Skripte in data/
Magento nur Ereignisbeobachter aufgerufen werden , die in diesem global
Bereich konfiguriert sind (siehe Magento-Strukturupdates vs. Datenupdates ). Bestimmte Beobachter wie enterprise_cms
und enterprise_search
für das Ereignis store_delete_after
sind in dem adminhtml
Bereich definiert , damit sie nicht hingerichtet werden. Das Löschen der Geschäftsansicht wird nicht wie ein im Backend ausgeführtes Löschen behandelt.
Wie gehen Sie mit solchen Vorgängen um? Zusätzliche Eventbereiche selbst in die Upgrade-Skripte laden (ich habe Angst davor)? Nehmen Sie im Upgrade-Skript keine derartigen Datenänderungen vor, sondern legen Sie Ihre magischen Scrips an einen heiligen, verborgenen Ort und führen Sie sie manuell aus.
quelle
Antworten:
So kurz nachdem ich dies an Matthias getwittert hatte, ging ich in Funkstille. Ich hoffe, Sie haben die Spannung gespürt, als Sie diese Antwort seit ein paar Wochen erwartet haben.
Was ich unter "Ich mache das in einer Warteschlange" verstehe, ist die direkte Antwort auf:
Warteschlangenmethode:
Wenn ich weiß, dass es bestimmte Ereignisse gibt, die im richtigen Kontext nicht ausgelöst werden (hauptsächlich für EE, aber möglicherweise in anderen Kontexten), schiebe ich die Löschung normalerweise in eine Warteschlange, damit sie im gewünschten Kontext ausgeführt wird .
Mit anderen Worten, erstellen Sie eine Warteschlangentabelle (oder Warteschlange / Thema in RabbitMQ usw.), die Details der Transaktion und der Ereignis-Hooks enthält, die sie abhören soll. Dies kann so elegant oder so simpel sein, wie Sie es möchten. Ist hier ein grundlegendes
Und dann bearbeiten Sie die Warteschlange später in einem CRON, in dem Sie nun steuern können, welcher Speicher "ausgeführt wird" (auch bekannt als "Administrator", Speicher 0):
Offensichtlich, wenn Sie Lust bekommen, wickeln Sie in einem Versuch / Fang und wickeln Sie in einer Transaktion. Ich denke, du verstehst das Wesentliche.
Dies ist wahrscheinlich die einzige Möglichkeit, den Kontext zu steuern, in dem das Ereignis ausgelöst wird.
Tandem-Ereignismethode:
Sie können die "adminhtml" -Methode manuell auslösen - Alan gibt eine anständige Erklärung dafür, was Sie tun würden, um das zu beeinflussen , aber im Grunde ist es dasselbe wie das Folgende :
Die Administratorversion des Kundenspeichers ruft den regulären Modellspeicher auf und löst anschließend das adminhtml-Ereignis aus. Sie können dies bei einem Beobachter auch umgekehrt tun, wenn Sie dies wünschen.
quelle
Verdammt, ich liebe mich ein bisschen, aber ich muss der Komplexität / Sprödigkeit des Transports der Task-Parameter und des Bereichs ( adminhtml | crontab | frontend | global | install ) in eine Warteschlange widersprechen , insbesondere wenn diese Warteschlange ausgeführt wird ein Magento-Kontext. Wenn es gemischte Kontexte gibt, die behandelt werden müssen, ist die Warteschlangenlösung eine Neuimplementierung des aktuellen "Problems"!
Ich denke, der Ansatz der Warteschlange ist spröde. Mein Argument ist, dass das vorzeitige Laden von Ereignisbereichen überhaupt kein Problem darstellt. Um dies zu erklären, wollen wir uns das Problem ansehen:
Um dies zu verstehen, müssen wir Ereignisbereiche im Ausführungskontext untersuchen. Matthias, ich stelle mir vor, dass du das schon weißt, aber für die Erbauung anderer:
Daten-Setup-Skripte werden ausgeführt,
Mage_Core_Model_App::run()
bevor die Anforderung an den Front Controller gesendet wird:Zu dem Zeitpunkt, an dem Daten-Setup-Skripte ausgeführt werden, wird der globale Ereignisbereich geladen. Die routing-kontextuellen Ereignisbereiche ( Frontend oder Adminhtml ) werden später
Mage_Core_Controller_Varien_Action::preDispatch()
als Ergebnis eines Routers geladen, der mit einer Controller-Aktion übereinstimmt (derarea
Name wird über die Vererbung festgelegt):Also normalerweise bei App - Initialisierung nur die Beobachter unter dem konfigurierten globalen Veranstaltungsbereich ausgeführt. Wenn das Setup-Skript etwas wie
Dann gibt es nur zwei Gefahren:
controller_front_init_before
oder zu beobachtencontroller_front_init_routers
# 1 sollte leicht zu finden sein. # 2 ist das eigentliche Problem und ich denke, dass Reflection das Problem lösen kann (beachte, dass ich mit Reflection absolut unerfahren bin):
Ich habe das nicht getestet, aber es entfernt den adminhtml-Ereignisindex und das entsprechende
Mage_Core_Model_App_Area
Objekt.quelle