ลบมุมมองร้านค้าโดยทางโปรแกรมในสคริปต์อัปเกรด


12

ฉันต้องการที่จะลบมุมมองการจัดเก็บโปรแกรม ดูMage_Adminhtml_System_StoreController::deleteStorePostAction()นี่เป็นเรื่องง่าย ๆ (ย่อรหัสเล็กน้อย):

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

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

ฉันต้องการใส่รหัสนี้ลงในสคริปต์อัปเกรดข้อมูลเพื่อให้การลบดำเนินการโดยอัตโนมัติ

ปัญหาคือขณะที่เรียกใช้สคริปต์อัปเกรดในdata/Magento จะเรียกเฉพาะผู้สังเกตเหตุการณ์ที่กำหนดค่าในglobalพื้นที่ (ดูการปรับปรุงโครงสร้างวีโอไอพีกับการอัพเดทข้อมูล ) ผู้สังเกตการณ์บางคนชอบenterprise_cmsและenterprise_searchสำหรับเหตุการณ์store_delete_afterที่กำหนดไว้ในadminhtmlพื้นที่เพื่อให้พวกเขาจะไม่ถูกประหารชีวิต การลบมุมมองร้านค้าจะไม่ได้รับการจัดการเหมือนกับการลบที่ดำเนินการในแบ็กเอนด์

คุณจัดการการดำเนินการเช่นนี้ได้อย่างไร โหลดพื้นที่กิจกรรมเพิ่มเติมด้วยตัวคุณเองในสคริปต์อัพเกรด (ฉันกลัวเรื่องนั้น) อย่าทำการดัดแปลงข้อมูลแบบนั้นในสคริปต์การอัปเกรด แต่ทำให้นักเวทย์ของคุณอยู่ในสถานที่ศักดิ์สิทธิ์ที่ซ่อนเร้นและดำเนินการด้วยตนเอง?


1
ทำไมคุณต้องลบมุมมองร้านค้าอย่างมีปัญหา?
oleksii.svarychevskyi

เนื่องจากเรามีหลายสภาพแวดล้อมและรวดเร็วและเชื่อถือได้มากกว่าในการเปลี่ยนแปลงการกำหนดค่าทั้งหมดโดยทางโปรแกรม
Matthias Zeis

เคยพบทางออกสำหรับสิ่งนี้หรือไม่? คุณจะทำสิ่งนี้บ่อยแค่ไหน? โดยส่วนตัวแล้วฉันจะไปที่ตัวเลือกที่สอง "อย่าทำการดัดแปลงข้อมูลอย่างนั้นในสคริปต์อัปเกรด แต่เอาสกิลเวทมนต์ของคุณไปไว้ในที่ซ่อนที่ศักดิ์สิทธิ์และดำเนินการด้วยตนเอง"
ProxiBlue

ฉันเลื่อนการแก้ไขปัญหานี้ออกไปเพราะมีสิ่งที่สำคัญกว่าที่ต้องทำ @philwinkle ของ Magento SE ตอบบน Twitter ว่า: "ฉันทำสิ่งนี้ในคิวหรือฟังและจุดไฟเหตุการณ์ adminhtml การจัดส่งแบบเดิม (หรือที่รู้จักว่าปลอม)" ( twitter.com/philwinkle/status/428183845985210369 ) ฉันเชื่อว่านี่มันเสี่ยงเกินไปสำหรับฉันและถึงแม้ว่าฉันจะไม่ชอบวิธีการนี้ แต่ฉันจะทำด้วยตนเอง
Matthias Zeis

@MatthiasZeis คุณสามารถเพิ่มเป็นคำตอบและยอมรับเพื่อให้คำถามที่ไม่ได้ตอบนับถอยหลังได้หรือไม่
Sander Mangel

คำตอบ:


6

ดังนั้นไม่นานหลังจากที่ฉันทวีตสิ่งนี้กับแมทเธียสชฉันก็เข้าสู่ความเงียบทางวิทยุ ฉันหวังว่าคุณจะรู้สึกใจจดใจจ่อขณะรอคำตอบนี้ไว้สองสามสัปดาห์แล้ว

สิ่งที่ฉันหมายถึงโดย "ฉันทำในคิว" คือการตอบสนองโดยตรงไปที่:

ผู้สังเกตการณ์บางคนเช่น enterprise_cms และ enterprise_search สำหรับ event store_delete_after ถูกกำหนดไว้ในพื้นที่ adminhtml เพื่อไม่ให้ถูกเรียกใช้งาน การลบมุมมองร้านค้าจะไม่ได้รับการจัดการเหมือนกับการลบที่ดำเนินการในแบ็กเอนด์

วิธีการคิว:

เมื่อฉันรู้ว่ามีเหตุการณ์บางอย่างที่จะไม่ดำเนินการในบริบทที่ถูกต้อง (ส่วนใหญ่สำหรับ EE แต่อาจนำไปใช้ในบริบทอื่น ๆ ) ฉันมักจะผลักการลบออกไปยังคิวเพื่อที่จะทำงานในบริบทที่ต้องการ .

กล่าวอีกนัยหนึ่งสร้างตารางคิว (หรือคิว / หัวข้อใน RabbitMQ ฯลฯ ) ที่จะมีรายละเอียดของการทำธุรกรรมและเบ็ดเหตุการณ์ที่มันควรจะฟัง สิ่งนี้อาจสวยงามหรือเรียบง่ายอย่างที่คุณต้องการ นี่คือพื้นฐาน

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

และจากนั้นทำงานคิวใน CRON ซึ่งคุณสามารถควบคุมได้ว่าร้านใดที่ "ทำงานอยู่" (หรือที่เรียกว่าคุณกำลังเรียกใช้งานราวกับว่าเป็นผู้ดูแลร้านค้า 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));
        }
    }
}

เห็นได้ชัดว่าถ้าคุณได้รับแฟนซีคุณห่อในลอง / จับและห่อในการทำธุรกรรม ฉันคิดว่าคุณได้รับส่วนสำคัญ

นี่เป็นวิธีเดียวที่เป็นไปได้ในการควบคุมบริบทที่เหตุการณ์เกิดเพลิงไหม้

วิธีการเหตุการณ์ตีคู่:

คุณสามารถใช้วิธี "adminhtml" ด้วยตนเองได้ - Alan ให้คำอธิบายที่ดีงามเกี่ยวกับสิ่งที่คุณทำเพื่อส่งผลกระทบต่อสิ่งนั้น แต่โดยหลักแล้วมันก็เป็นเช่นนี้:

#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()
    ));        
    //..
}

รุ่นผู้ดูแลระบบของลูกค้าบันทึกการโทรรุ่นบันทึกปกติและส่งเหตุการณ์ adminhtml หลังจากนั้น คุณสามารถทำสิ่งนี้ได้ในผู้สังเกตการณ์หากคุณต้องการ


5

Dammit ฉันรักฉัน philwinkle แต่ฉันไม่เห็นด้วยกับความซับซ้อน / ความเปราะบางของการขนส่งพารามิเตอร์งานและพื้นที่ ( adminhtml | crontab | frontend | global | ติดตั้ง ) ไปยังคิวโดยเฉพาะถ้าคิวนั้นจะถูกดำเนินการ บริบทวีโอไอพี หากมีบริบทผสมที่ต้องการการจัดการการแก้ปัญหาคิวคือการนำ "ปัญหา" มาใช้ใหม่!

ฉันคิดว่าวิธีการเข้าคิวนั้นเปราะ ข้อโต้แย้งของฉันคือการโหลดพื้นที่กิจกรรมก่อนกำหนดไม่ใช่ปัญหาจริงๆ เพื่ออธิบายสิ่งนี้ลองสำรองและดูปัญหา:

อันตรายของการโหลดพื้นที่กิจกรรมก่อนกำหนดในขอบเขตการดำเนินการคืออะไร?

เพื่อทำความเข้าใจนี้เราต้องตรวจสอบพื้นที่กิจกรรมในบริบทการดำเนินการ แมทเธียสชฉันนึกว่าคุณรู้เรื่องนี้อยู่แล้ว แต่เพื่อคนอื่น

สคริปต์การตั้งค่าข้อมูลจะดำเนินการMage_Core_Model_App::run()ก่อนที่จะส่งคำขอไปยัง Front Controller:

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;
}

โดยสคริปต์การตั้งค่าข้อมูลเวลากำลังดำเนินการโหลดพื้นที่เหตุการณ์ทั่วโลก พื้นที่กิจกรรมการกำหนดเส้นทางตามบริบท ( frontendหรือadminhtml ) ถูกโหลดในภายหลังMage_Core_Controller_Varien_Action::preDispatch()เนื่องจากเราเตอร์จับคู่การกระทำของตัวควบคุม ( areaชื่อถูกตั้งค่าผ่านการสืบทอด):

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

ดังนั้นตามปกติในระหว่างการเตรียม app เฉพาะผู้สังเกตการณ์การกำหนดค่าภายใต้โลกพื้นที่จัดกิจกรรมที่จะดำเนินการ หากสคริปต์การตั้งค่าทำบางสิ่งเช่น

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

จากนั้นมีเพียงสองอันตราย:

  1. ผู้สังเกตการณ์ได้รับการกำหนดค่าอย่างไม่ถูกต้องภายใต้adminhtmlเพื่อสังเกตเหตุการณ์ที่ไม่เกิดบริบทเช่นcontroller_front_init_beforeหรือcontroller_front_init_routers
  2. คำขอคือคำขอส่วนหน้า

# 1 ควร grep ง่าย # 2 เป็นความกังวลที่แท้จริงและฉันคิดว่า Reflection สามารถแก้ปัญหาได้ (โปรดทราบว่าฉันไม่มีประสบการณ์ในการใช้การสะท้อนกลับ):

<?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()

ฉันไม่ได้ทำการทดสอบนี้ แต่มันจะลบดัชนีเหตุการณ์ adminhtml และMage_Core_Model_App_Areaวัตถุที่เกี่ยวข้อง


1
ฉันไม่คู่ควร !! ฉันไม่คู่ควร !!!!
philwinkle
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.