Yükseltme komut dosyasında mağaza görünümünü programlı olarak silme


12

Mağaza görünümünü programlı olarak silmek istiyorum . Bakmak Mage_Adminhtml_System_StoreController::deleteStorePostAction(), bu oldukça kolay (biraz kısaltılmış kod):

$model = Mage::getModel('core/store')->load($id);

if ($model->getId() && $model->isCanDelete()) {
    $model->delete();
    Mage::dispatchEvent('store_delete', array('store' => $model));
}

Silme otomatik olarak yürütülecek şekilde bu kodu bir veri yükseltme komut dosyasına koymak istiyorum .

Sorun, data/Magento'da yükseltme komut dosyalarını yürütürken yalnızca bölgede yapılandırılmış olay gözlemcilerini çağırmasıdır (bkz. Magento Yapı Güncellemeleri ve Veri Güncellemeleri ). Etkinlik gibi ve etkinlik için bazı gözlemciler bölgede tanımlanmazlar, böylece yürütülmezler. Mağaza görünümü silme arka uçta yürütülen bir silme gibi ele alınmaz.globalenterprise_cmsenterprise_searchstore_delete_afteradminhtml

Böyle operasyonları nasıl idare ediyorsunuz? Ek olay alanlarını yükseltme komut dosyalarına kendiniz yükleyin (bundan korkuyorum)? Yükseltme komut dosyasında böyle veri değişiklikleri yapmayın, ancak sihirli komut dosyalarınızı kutsal bir gizli yere koyun ve manuel olarak yürütün?


1
Mağaza görünümünü neden sorunlu olarak silmeniz gerekiyor?
oleksii.svarychevskyi

Çünkü birkaç ortamımız var ve tüm yapılandırma değişikliklerini programlı olarak yapmak daha hızlı ve daha güvenilir.
Matthias Zeis

Bunun için bir çözüm buldunuz mu? Bunu ne sıklıkla yaparsınız? Şahsen, ikinci seçenek için "yükseltme komut dosyasında böyle veri değişiklikleri yapmayın, ancak sihirli komut dosyalarınızı kutsal bir gizli yere koyun ve manuel olarak çalıştırın?"
ProxiBlue

Bu sorunu erteledim çünkü yapılacak daha önemli şeyler vardı. Magento SE'nin kendi @philwinkle Twitter'ında şöyle cevap verdi: "Bunları bir kuyrukta yaparım; veya bir tandem adminhtml gönderim etkinliğini (sahte olarak da denir) dinler ve başlatır" ( twitter.com/philwinkle/status/428183845985210369 ). Bunun benim için çok riskli olduğuna inanıyorum ve bu yaklaşımı sevmeme rağmen manuel olarak yapacağım.
Matthias Zeis

@MatthiasZeis bunu bir cevap olarak ekleyebilir ve cevaplanmamış soruların geri sayımını devam ettirmek için kabul edebilir misiniz?
Sander Mangel

Yanıtlar:


6

Bunu Matthias'a tweetledikten kısa bir süre sonra radyo sessizliğine gittim. Umarım birkaç hafta boyunca bu cevabı beklerken şüpheyi hissettin.

"Bunları bir kuyrukta yapıyorum" ile kastettiğim doğrudan yanıt:

Store_delete_after olayı için enterprise_cms ve enterprise_search gibi belirli gözlemciler adminhtml alanında tanımlandığından yürütülmezler. Mağaza görünümü silme arka uçta yürütülen bir silme gibi ele alınmaz.

Kuyruk Yöntemi:

Doğru bağlamda tetiklenmeyecek belirli olaylar olduğunu bildiğimde (çoğunlukla EE için, ancak diğer bağlamlarda geçerli olabilir), genellikle silme işlemini bir kuyruğa iterim, böylece ihtiyaç duyduğu bağlamda çalışır .

Başka bir deyişle, işlemin ayrıntılarını ve dinlemesi gereken olay kancalarını içeren bir kuyruk tablosu (veya RabbitMQ'da kuyruk / konu vb.) Oluşturun. Bu, olmasını istediğiniz kadar zarif veya basit olabilir. İşte temel

$queue = Mage::getModel('yourcompany/queue_job')
         ->setJobType('delete')
         ->setEntityType('core/store')
         ->setEntityId(12)
         ->setDispatchEvent('store_delete')
         ->setDispatchEventDataKey('store')
         ->save();

Ve daha sonra kuyruğu daha sonra hangi mağazanın "çalıştığını" kontrol ettiğiniz bir CRON'da çalışın (aka sadece yöneticiymiş gibi çalıştırıyorsunuz, mağaza 0):

foreach(Mage::getModel('yourcompany/queue_job')->getCollection() as $job){
    if($job->getJobType()=='delete'){

        $model = Mage::getModel($this->getEntityType())->load($this->getEntityId());

        if ($model->getId() && $model->isCanDelete()) {
            $model->delete();
            Mage::dispatchEvent($job->getDispatchEvent(), array($job->setDispatchEventDataKey() => $model));
        }
    }
}

Açıkçası fantezi alıyorsanız bir deneyin / yakalamak ve bir işlem sarın. Sanırım özü aldın.

Olayın gerçekleştiği bağlamı kontrol etmenin tek yolu bu olabilir.

Tandem olay yöntemi:

"Adminhtml" yöntemini kendiniz manuel olarak tetikleyebilirsiniz - Alan, bunu etkilemek için ne yapacağınız hakkında oldukça iyi bir açıklama verir , ancak aslında bu aynıdır:

#File: app/code/core/Mage/Adminhtml/controllers/CustomerController.php
public function saveAction()
{
    //...
    $customer->save();
    //...
    Mage::dispatchEvent('adminhtml_customer_prepare_save', array(
        'customer'  => $customer,
        'request'   => $this->getRequest()
    ));        
    //..
}

Müşteri kaydının yönetici sürümü normal model kaydetmeyi çağırır ve daha sonra adminhtml olayını gönderir. İsterseniz bunun tersini bir gözlemcide yapabilirsiniz.


5

Lanet olsun, bana bazı philwinkle seviyorum, ama görev parametrelerini ve alanı ( adminhtml | crontab | frontend | global | install ) bir kuyruğa taşımanın karmaşıklığına / kırılganlığına katılmıyorum , özellikle de bu kuyruk yürütülecekse Magento bağlamı. Ele alınması gereken karışık bağlamlar varsa, kuyruk çözümü mevcut "sorunun" yeniden uygulanmasıdır!

Bence kuyruk yaklaşımı kırılgandır. Benim iddiam, olay alanlarını erken yüklemenin gerçekten bir sorun olmadığıdır. Bunu açıklamak için, geri dönelim ve soruna bakalım:

Bir olay alanını erken yürütme kapsamında yükleme tehlikesi nedir?

Bunu anlamak için, yürütme bağlamındaki olay alanlarını incelemeliyiz. Matthias, bunu zaten bildiğini sanıyorum, ama başkalarının kurguları için:

Veri kurulum komut dosyaları Mage_Core_Model_App::run(), isteği Ön Denetleyiciye göndermeden önce yürütülür :

public function run($params)
{
    $options = isset($params['options']) ? $params['options'] : array();
    $this->baseInit($options);
    Mage::register('application_params', $params);

    if ($this->_cache->processRequest()) {
        $this->getResponse()->sendResponse();
    } else {
        $this->_initModules();
//Global event area is loaded here
        $this->loadAreaPart(Mage_Core_Model_App_Area::AREA_GLOBAL, Mage_Core_Model_App_Area::PART_EVENTS);

        if ($this->_config->isLocalConfigLoaded()) {
            $scopeCode = isset($params['scope_code']) ? $params['scope_code'] : '';
            $scopeType = isset($params['scope_type']) ? $params['scope_type'] : 'store';
            $this->_initCurrentStore($scopeCode, $scopeType);
            $this->_initRequest();
//Data setup scripts are executed here: 
            Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
        }

        $this->getFrontController()->dispatch();
    }
    return $this;
}

Veri kurulum komut dosyaları yürütülürken global olay alanı yüklenir. Yönlendirme bağlamsal olay alanları ( ön uç veya adminhtml ), Mage_Core_Controller_Varien_Action::preDispatch()bir denetleyici eylemiyle eşleşen yönlendiricinin bir sonucu olarak yüklenir ( areaad, devralma yoluyla ayarlanır):

public function preDispatch()
{
    //...
    Mage::app()->loadArea($this->getLayout()->getArea());
    //...
}

Bu nedenle normalde uygulama başlatma sırasında yalnızca global olay alanı altında yapılandırılan gözlemciler yürütülür. Kurulum betiği aşağıdaki gibi bir şey yaparsa

$this->loadAreaPart(Mage_Core_Model_App_Area::AREA_ADMINHTML, Mage_Core_Model_App_Area::PART_EVENTS);

o zaman sadece iki tehlike vardır:

  1. Gözlemci altında yanlış yapılandırmadığınızdan edilmiş adminhtml bir bağlam az etkinlik gözlemlemek gibi controller_front_init_beforeya dacontroller_front_init_routers
  2. İstek bir ön uç isteğidir.

# 1 için grep kolay olmalı. # 2 asıl endişe ve Yansıma'nın sorunu çözebileceğini düşünüyorum.

<?php

//Start setup script as normal
$installer = $this;
$installer->startSetup()

//Load adminhtml event area
Mage::app()->loadAreaPart(
    Mage_Core_Model_App_Area::AREA_ADMINHTML,
    Mage_Core_Model_App_Area::PART_EVENTS
);

// your setup script logic here

//I hope this isn't a bad idea.
$reflectedApp = new ReflectionClass('Mage_Core_Model_App');
$_areas = $reflectedApp->getProperty('_areas');
$_areas->setAccessible(true);
$areas = $_areas->getValue(Mage::app());
unset($areas['adminhtml']);
$_areas->setValue(Mage::app(),$areas); //reset areas

//End setup script as normal
$installer->endSetup()

Bunu test etmedim, ancak adminhtml olay dizinini ve ilgili Mage_Core_Model_App_Areanesneyi kaldırır .


1
Ben layık değilim !! Ben layık değilim !!!!
philwinkle
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.