Quero excluir uma visão da loja programaticamente . Olhando Mage_Adminhtml_System_StoreController::deleteStorePostAction()
, isso é bastante fácil (código reduzido um pouco):
$model = Mage::getModel('core/store')->load($id);
if ($model->getId() && $model->isCanDelete()) {
$model->delete();
Mage::dispatchEvent('store_delete', array('store' => $model));
}
Quero colocar esse código em um script de atualização de dados para que a exclusão seja executada automaticamente.
O problema é que, ao executar os scripts de atualização no data/
Magento, apenas chama observadores de eventos configurados na global
área (consulte Atualizações de estrutura do Magento vs. Atualizações de dados ). Certos observadores como enterprise_cms
e enterprise_search
para o evento store_delete_after
são definidos na adminhtml
área para que não sejam executados. A exclusão da visualização da loja não será tratada como uma exclusão executada no back-end.
Como você lida com operações como esta? Carregue você mesmo áreas de eventos adicionais nos scripts de atualização (eu tenho medo disso)? Não faça modificações de dados como essa no script de atualização, mas coloque seus scripts mágicos em um local sagrado e oculto e execute-os manualmente?
fonte
Respostas:
Então, pouco depois de tuitá-lo para Matthias, fiquei em silêncio no rádio. Espero que tenha sentido o suspense, pois aguarda esta resposta há algumas semanas.
O que quero dizer com "faço isso em uma fila" está em resposta direta a:
Método da fila:
Quando eu sei que existem certos eventos que não são acionados no contexto correto (principalmente para EE, mas podem ser aplicados em outros contextos), normalmente empurro a exclusão para uma fila para que ela seja executada no contexto necessário. .
Em outras palavras, crie uma tabela de filas (ou fila / tópico no RabbitMQ etc.) que contenha detalhes da transação e os ganchos de eventos que devem estar ouvindo. Isso pode ser tão elegante ou simplista quanto você deseja. Aqui está um básico
E trabalhe a fila posteriormente em um CRON, onde agora você tem controle sobre qual loja está "executando" (ou seja, você está executando apenas como se fosse o administrador, loja 0):
Obviamente, se você estava começando a gostar de uma tentativa / captura e quebra em uma transação. Eu acho que você entendeu.
Essa é a única maneira viável de controlar o contexto em que o evento é disparado.
Método de evento tandem:
Você pode disparar o método "adminhtml" manualmente - Alan dá uma explicação bastante decente do que você faria para afetar isso , mas essencialmente é o mesmo:
A versão administrativa do save do cliente chama o modelo regular de save e despacha o evento adminhtml posteriormente. Você pode fazer o inverso disso em um observador, se assim o desejar.
fonte
Droga, eu amo algumas coisas, mas tenho que discordar da complexidade / fragilidade de transportar os parâmetros da tarefa e a área ( adminhtml | crontab | frontend | global | install ) para uma fila, especialmente se essa fila estiver em execução um contexto Magento. Se houver contextos mistos que precisam ser manipulados, a solução da fila é uma reimplementação do "problema" atual!
Eu acho que a abordagem da fila é quebradiça. Meu argumento é que carregar áreas de eventos prematuramente não é realmente um problema. Para explicar isso, vamos voltar e analisar o problema:
Para entender isso, devemos examinar as áreas de eventos no contexto de execução. Matthias, imagino que você já saiba disso, mas para a edificação de outras pessoas:
Os scripts de configuração de dados são executados
Mage_Core_Model_App::run()
antes do envio da solicitação ao Front Controller:No momento em que os scripts de configuração de dados estão sendo executados, a área de eventos globais é carregada. As áreas de eventos contextuais de roteamento ( frontend ou adminhtml ) são carregadas posteriormente
Mage_Core_Controller_Varien_Action::preDispatch()
como resultado do roteador correspondente a uma ação do controlador (oarea
nome é definido por herança):Portanto, normalmente durante a inicialização do aplicativo, apenas os observadores configurados na área de eventos globais serão executados. Se o script de instalação fizer algo como
então existem apenas dois perigos:
controller_front_init_before
oucontroller_front_init_routers
O número 1 deve ser fácil de saudar. O número 2 é a verdadeira preocupação, e acho que o Reflection pode resolver o problema (note que sou extremamente inexperiente em usar o reflexo):
Eu não testei isso, mas ele remove o índice de eventos adminhtml e o
Mage_Core_Model_App_Area
objeto correspondente .fonte