Khỉ thật, tôi yêu tôi một chút, nhưng tôi không đồng ý với sự phức tạp / giòn của việc vận chuyển các tham số nhiệm vụ và khu vực ( adminhtml | crontab | frontend | global | install ) vào hàng đợi, đặc biệt nếu hàng đợi đó sẽ được thực thi một bối cảnh Magento. Nếu có các bối cảnh hỗn hợp cần xử lý thì giải pháp hàng đợi là sự thực hiện lại "vấn đề" hiện tại!
Tôi nghĩ rằng cách tiếp cận hàng đợi là dễ vỡ. Lập luận của tôi là việc tải các khu vực sự kiện sớm không thực sự là một vấn đề. Để giải thích điều này, hãy sao lưu và xem xét vấn đề:
Nguy hiểm của việc tải một khu vực sự kiện sớm trong một phạm vi thực thi là gì?
Để hiểu điều này, chúng ta phải kiểm tra các khu vực sự kiện trong bối cảnh thực hiện. Matthias, tôi tưởng tượng rằng bạn đã biết điều này, nhưng đối với sự chỉnh sửa của người khác:
Các tập lệnh thiết lập dữ liệu được thực thi Mage_Core_Model_App::run()
trước khi gửi yêu cầu tới Bộ điều khiển phía trước:
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;
}
Vào thời điểm các tập lệnh thiết lập dữ liệu đang thực thi, khu vực sự kiện toàn cầu được tải. Các khu vực sự kiện định tuyến theo ngữ cảnh ( frontend hoặc adminhtml ) được tải sau này Mage_Core_Controller_Varien_Action::preDispatch()
do bộ định tuyến khớp với hành động của bộ điều khiển ( area
tên được đặt thông qua kế thừa):
public function preDispatch()
{
//...
Mage::app()->loadArea($this->getLayout()->getArea());
//...
}
Vì vậy, thông thường trong quá trình khởi tạo ứng dụng, chỉ những người quan sát được cấu hình trong khu vực sự kiện toàn cầu sẽ được thực thi. Nếu tập lệnh thiết lập làm một cái gì đó như
$this->loadAreaPart(Mage_Core_Model_App_Area::AREA_ADMINHTML, Mage_Core_Model_App_Area::PART_EVENTS);
sau đó chỉ có hai nguy hiểm:
- Một người quan sát đã bị định cấu hình sai dưới adminhtml để quan sát một sự kiện không có ngữ cảnh như
controller_front_init_before
hoặccontroller_front_init_routers
- Yêu cầu là một yêu cầu frontend .
# 1 nên dễ grep cho. # 2 là mối quan tâm thực sự và tôi nghĩ rằng Reflection có thể giải quyết vấn đề (lưu ý rằng tôi thiếu kinh nghiệm trong việc sử dụng sự phản chiếu):
<?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()
Tôi đã không kiểm tra điều này, nhưng nó loại bỏ chỉ số sự kiện adminhtml và Mage_Core_Model_App_Area
đối tượng tương ứng .