Je souhaite supprimer une vue de magasin par programme . En regardant Mage_Adminhtml_System_StoreController::deleteStorePostAction()
, c'est assez facile (code abrégé un peu):
$model = Mage::getModel('core/store')->load($id);
if ($model->getId() && $model->isCanDelete()) {
$model->delete();
Mage::dispatchEvent('store_delete', array('store' => $model));
}
Je veux mettre ce code dans un script de mise à niveau des données afin que la suppression soit exécutée automatiquement.
Le problème est que lors de l'exécution des scripts de mise à niveau dans data/
Magento, seuls les observateurs d'événements configurés dans la global
zone sont appelés (voir Mises à jour de structure Magento vs Mises à jour de données ). Certains observateurs comme enterprise_cms
et enterprise_search
pour l'événement store_delete_after
sont définis dans la adminhtml
zone afin qu'ils ne soient pas exécutés. La suppression de la vue du magasin ne sera pas traitée comme une suppression exécutée dans le backend.
Comment gérez-vous des opérations comme celle-ci? Chargez vous-même des zones d'événements supplémentaires dans les scripts de mise à niveau (j'en ai peur)? Ne faites pas de modifications de données comme celle-ci dans le script de mise à niveau, mais placez vos scripts magiques dans un endroit caché sacré et exécutez-les manuellement?
la source
Réponses:
Donc, peu de temps après avoir tweeté cela à Matthias, je suis resté silencieux à la radio. J'espère que vous avez ressenti le suspense en attendant cette réponse depuis quelques semaines maintenant.
Ce que je veux dire par «je fais ça dans une file d'attente» est en réponse directe à:
Méthode de file d'attente:
Quand je sais qu'il y a certains événements qui ne se déclencheront pas dans le contexte correct (principalement pour EE, mais peuvent s'appliquer dans d'autres contextes), je pousse généralement la suppression dans une file d'attente afin qu'elle s'exécute dans le contexte dont elle a besoin. .
En d'autres termes, créez une table de file d'attente (ou file d'attente / rubrique dans RabbitMQ, etc.) qui contiendrait les détails de la transaction et les hooks d'événement qu'elle devrait écouter. Cela peut être aussi élégant ou aussi simpliste que vous le souhaitez. Voici une base
Et puis travaillez la file d'attente plus tard dans un CRON, où vous avez maintenant le contrôle sur le magasin qui est "en cours d'exécution" (c'est-à-dire que vous l'exécutez comme s'il s'agissait de l'administrateur, le magasin 0):
Évidemment, si vous deveniez fantaisiste, vous encapsulez dans un essai / capture et encapsulez dans une transaction. Je pense que vous obtenez l'essentiel.
C'est probablement le seul moyen de contrôler le contexte dans lequel l'événement se déclenche.
Méthode d'événement en tandem:
Vous pouvez déclencher la méthode "adminhtml" vous-même manuellement - Alan donne une explication assez décente de ce que vous feriez pour affecter cela , mais essentiellement c'est la même chose que ceci:
La version d'administration de la sauvegarde client appelle la sauvegarde de modèle standard et distribue ensuite l'événement adminhtml. Vous pouvez faire l'inverse chez un observateur si vous le souhaitez.
la source
Bon sang, je m'aime un peu, mais je dois être en désaccord avec la complexité / fragilité du transport des paramètres de la tâche et de la zone ( adminhtml | crontab | frontend | global | install ) vers une file d'attente, surtout si cette file d'attente doit être en cours d'exécution un contexte Magento. S'il existe des contextes mixtes qui doivent être traités, la solution de file d'attente est une réimplémentation du "problème" actuel!
Je pense que l'approche de la file d'attente est fragile. Mon argument est que le chargement prématuré des zones d'événements n'est pas vraiment un problème. Pour expliquer cela, revenons en arrière et examinons le problème:
Pour comprendre cela, nous devons examiner les zones d'événements dans le contexte d'exécution. Matthias, j'imagine que vous le savez déjà, mais pour l'édification des autres:
Les scripts de configuration des données sont exécutés
Mage_Core_Model_App::run()
avant d'envoyer la demande au contrôleur frontal:Au moment où les scripts de configuration des données s'exécutent, la zone d'événements globale est chargée. Les zones d'événements contextuelles de routage ( frontend ou adminhtml ) sont chargées plus tard à
Mage_Core_Controller_Varien_Action::preDispatch()
la suite de la correspondance du routeur avec une action du contrôleur (learea
nom est défini via l'héritage):Ainsi, normalement lors de l'initialisation de l'application, seuls les observateurs configurés sous la zone d'événement global seront exécutés. Si le script de configuration fait quelque chose comme
alors il n'y a que deux dangers:
controller_front_init_before
oucontroller_front_init_routers
# 1 devrait être facile à comprendre. # 2 est la vraie préoccupation, et je pense que la réflexion peut résoudre le problème (notez que je suis terriblement inexpérimenté avec la réflexion):
Je n'ai pas testé cela, mais cela supprime l'index des événements adminhtml et l'
Mage_Core_Model_App_Area
objet correspondant .la source