업그레이드 스크립트에서 프로그래밍 방식으로 상점보기 삭제


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입니다 ( Magento 구조 업데이트 및 데이터 업데이트 참조 ). 이벤트 enterprise_cms와 같은 특정 관찰자 는 해당 영역 에서 정의 되므로 실행되지 않습니다. 스토어 뷰 삭제는 백엔드에서 실행 된 삭제처럼 처리되지 않습니다.enterprise_searchstore_delete_afteradminhtml

이와 같은 작업을 어떻게 처리합니까? 업그레이드 스크립트에 추가 이벤트 영역을 직접로드하십시오 (두려우십니까)? 업그레이드 스크립트에서와 같은 데이터 수정을 수행하지 말고 마법의 흠집을 신성한 숨겨진 장소에 넣고 수동으로 실행 하시겠습니까?


1
문제가있는 상점보기를 삭제해야하는 이유는 무엇입니까?
oleksii.svarychevskyi

여러 환경이 있으며 프로그래밍 방식으로 모든 구성 변경을 수행하는 것이 더 빠르고 안정적이기 때문입니다.
Matthias Zeis

이것에 대한 해결책을 찾은 적이 있습니까? 얼마나 자주 이렇게 하시겠습니까? 개인적으로, 나는 두 번째 옵션 인 "업그레이드 스크립트에서 데이터를 수정하지 말고 마법의 흠집을 신성한 숨겨진 장소에두고 수동으로 실행 하시겠습니까?"
ProxiBlue

더 중요한 일이 있었기 때문에이 문제를 연기했습니다. Magento SE의 자체 @philwinkle은 Twitter에서 "대기열에서 이러한 작업을 수행하거나 탠덤 관리 HTML 디스패치 이벤트 (일명 가짜)"를 듣고 실행합니다 ( twitter.com/philwinkle/status/428183845985210369 ). 나는 이것이 나에게 너무 위험하다고 생각하지만이 접근법을 좋아하지 않지만 수동으로 할 것입니다.
Matthias Zeis

@ MatthiasZeis 당신은 대답으로 추가하고 대답하지 않은 질문을 카운트 다운하기 위해 그것을 받아 들일 수 있습니까?
Sander Mangel

답변:


6

그래서 이것을 Matthias에 트윗 한 직후 나는 라디오 침묵을 밟았습니다. 몇 주 동안이 답변을 기다리면서 긴장감을 느꼈기를 바랍니다.

"대기열에서이 작업을 수행합니다"는 다음에 직접 응답합니다.

store_delete_after 이벤트에 대한 enterprise_cms 및 enterprise_search와 같은 특정 옵저버는 adminhtml 영역에 정의되어 실행되지 않습니다. 스토어 뷰 삭제는 백엔드에서 실행 된 삭제처럼 처리되지 않습니다.

대기열 방법 :

올바른 컨텍스트에서 발생하지 않는 특정 이벤트가 있음을 알면 (주로 EE의 경우이지만 다른 컨텍스트에서 적용될 수 있음) 일반적으로 삭제를 큐에 밀어 넣어 필요한 컨텍스트에서 실행되도록합니다. .

즉, 트랜잭션 및 수신 대기해야하는 이벤트 후크의 세부 사항을 포함 하는 큐 테이블 (또는 RabbitMQ 등의 큐 / 토픽 등)을 작성하십시오. 이것은 원하는만큼 우아하거나 단순 할 수 있습니다. 기본은 다음과 같습니다

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

그런 다음 나중에 CRON에서 대기열을 작업하십시오. 이제 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));
        }
    }
}

분명히 당신이 공상을 얻는다면 당신은 try / catch에 싸서 거래에 싸입니다. 나는 당신이 요점을 얻는다고 생각합니다.

이것은 이벤트가 발생하는 컨텍스트를 제어 할 수있는 유일한 방법 일 것입니다.

직렬 이벤트 방법 :

"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

젠장, 나는 약간의 역설을 좋아하지만 , 특히 대기열이 실행 될 경우 작업 매개 변수 영역 ( adminhtml | crontab | frontend | global | install )을 대기열 로 전송하는 복잡성 / 취성에 동의하지 않아야합니다 마 젠토 컨텍스트. 처리해야하는 혼합 컨텍스트가있는 경우 큐 솔루션은 현재 "문제"를 다시 구현 한 것입니다!

대기열 접근 방식이 취 약하다고 생각합니다. 내 주장은 이벤트 영역을 조기에로드하는 것이 실제로 문제가되지 않는다는 것입니다. 이를 설명하기 위해 백업하고 문제를 살펴 보자.

실행 범위에서 이벤트 영역을 조기에로드하면 어떤 위험이 있습니까?

이를 이해하려면 실행 컨텍스트에서 이벤트 영역을 조사해야합니다. 마티아스, 나는 당신이 이미 이것을 알고 있지만 다른 사람들의 교화를 위해 상상합니다.

Mage_Core_Model_App::run()요청을 프론트 컨트롤러로 디스패치하기 전에 데이터 설정 스크립트가 실행됩니다 .

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

따라서 일반적으로 앱을 초기화하는 동안 전역 이벤트 영역 에서 구성된 관찰자 만 실행됩니다. 설정 스크립트가 다음과 같은 작업을 수행하는 경우

$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은 잡기 쉬워야합니다. # 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.