运行升级脚本时当前存储为1


15

知道Mage::app()->getStore()在我运行升级脚本的独立于商店视图的升级脚本中时,为什么返回ID为1的商店视图吗?
我的意思是,我知道执行此操作的代码在哪里。其中Mage_Core_Model_App::getStore()有:

    if (!Mage::isInstalled() || $this->getUpdateMode()) {
        return $this->_getDefaultStore();
    }

_getDefaultStore看起来像这样:

   if (empty($this->_store)) {
        $this->_store = Mage::getModel('core/store')
            ->setId(self::DISTRO_STORE_ID)
            ->setCode(self::DISTRO_STORE_CODE);
    }
    return $this->_store;

$this->_store 达到上述方法时始终为空。

即使将其添加到升级脚本的顶部,我也会得到相同的结果:

Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));

我对具有此“功能”的业务逻辑感到好奇。


我认为升级脚本始终在前端范围内运行。我经常告诉升级脚本明确地将管理存储区用于以下各行。
bukart 2014年

@bukart。我尝试明确告诉升级脚本运行管理商店视图,但是得到的结果相同。请参阅问题的最后3行。
马里斯(Marius)

我试图在下面回答您的问题
bukart 2014年

Answers:


5

注意:不要忘记在进行调度和Mage_Adminhtml_Controller_Action执行扩展控制器之前未设置管理存储范围(请参阅中的adminhtml_controller_action_predispatch_start事件和相关观察者Mage_Adminhtml_Controller_Action::preDispatch())。

我对具有此“功能”的业务逻辑感到好奇。

你不是唯一的一个。也就是说,除非MosheDima想要讨论,否则我们可能永远不知道。

设置脚本在应用程序初始化的早期执行。这样做的设计可能是由于在执行其余的堆栈时,“迁移”完成了必要的迁移和其他工作-这意味着即使安装了模块,系统也可以立即使用或升级。我想知道原始的架构师最初是否曾想过需要一个更加初始化的系统。 我猜想,尽管许多代码都假设有一个可用的商店实例,但是_getDefaultStore()逻辑确保存在一个商店实例。

完整范围设置可在1.4.0.0及更高版本中通过数据设置脚本获得。


3

好的,要在升级脚本中使用管理存储,只需使用

Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

您的方法Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID)); 无法成功,因为没有真正可用于管理员的可加载商店视图

我经常使用这样的模式:

// remembering old current store
$currentStore = Mage::app()->getCurrentStore();

// switching to admin store
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

// switching back to old current store
Mage::app()->setCurrentStore($currentStore->getStoreId());

否则,有时在执行升级脚本后,有时会将您的访问者重定向到管理页面,而不是前端。


更新:

我误解了以下问题,因此这是一种尝试解释^^的新方法

升级脚本是从核心(Mage_Core_Model_Resource_Setup::_modifyResourceDb(...))中更深层的方法调用的

在这里我试图列出堆栈

  • Mage_Core_Model_App::run($params)

  • Mage_Core_Model_App::_initModules()

  • Mage_Core_Model_Resource_Setup::applyAllUpdates()

  • Mage_Core_Model_Resource_Setup::applyUpdates()

  • Mage_Core_Model_Resource_Setup::_upgradeResourceDb($oldVersion, $newVersion)

  • Mage_Core_Model_Resource_Setup::_modifyResourceDb($actionType, $fromVersion, $toVersion)

现在看看Mage_Core_model_App::run($params)

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();
        $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();
            Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
        }

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

该方法_initModules()$scopeCode$scopeType确定之前被调用。

目前,我无法弄清楚假定的回退定义在哪里。


哦,但是有一个可供管理员加载的商店视图。看看core_store桌子。有一个ID为的记录0。另外,如果您尝试此操作var_dump(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID)),则将获得管理商店的有效实例。也尝试过,Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);但我得到相同的结果。但是我的问题不是关于如何在升级脚本中设置管理存储。我在问为什么Mage::app()->getStore()在升级脚本中返回ID为1的商店。
马里乌斯

哦...对...确实有一个数据库管理仓库。
bukart 2014年

1
嗯...我知道筹码,但是现在我已经在你的答案中看到了,它击中了我。更新应该以某种方式“无状态”运行。但是,要运行某种东西,您需要一家商店。因此,商店的默认值。现在唯一没有意义的是:为什么此默认存储区不是0(admin),并且是可以轻松从admin UI中删除的存储区视图?+1睁开眼睛。如果对此没有其他明确的答案,我会接受。
马里斯(Marius)

嗯...好问题...也许午饭后我来看一下...有趣的^^
bukart 2014年

从1.9.3.6版本开始,Mage::app()->getCurrentStore();它似乎未定义,在调用时会出现致命错误。相反,我使用来获得ID $currentStoreId = Mage::app()->getStore()->getId();
埃里克·海斯特兰德

2

所以基本的答案是,如果.....等待什么,它实际上进入了第三个。

if (!isset($id) || ''===$id || $id === true) {
    $id = $this->_currentStore;
}

对我来说,它返回true Mage::isInstalled()和false $this->getUpdateMode()听起来是错误的。但这只会在的第一个命中时发生getStore

因此,它似乎在设置更新模式之前就设置了商店,然后在设置脚本中返回时,它将使用默认的商店调用,该调用使用以下代码:

$this->_store = Mage::getModel('core/store')
    ->setId(self::DISTRO_STORE_ID)
    ->setCode(self::DISTRO_STORE_CODE);

self::DISTRO_STORE_ID我认为是因为它的值是1,它需要一些东西,并且没有设置给我们管理商店:(

所以我实际上有一个没有存储ID为1的系统,并且更新脚本似乎运行良好。如果我们要添加表/属性,那很好,即使添加特定于站点的cms块也可以,但是我们确实获得了所有商店ID,并在保存商店特定数据时进行了专门设置。


我挖了同样的东西。我不明白的是“ Magento为什么不使用管理员存储进行升级?”。它的接缝更加合理。我不敢想,如果我删除该存储ID为1会发生什么
马吕斯

没有人会疯狂到删除默认存储区;)
David Manners 2014年

既然我知道了这一点,我就不会发疯了,但是事实是有可能……很好……永远不要信任用户。
马里乌斯

我们的一位总理问我上周是否可以拆除旧店。我想我回答了“可能发生的最坏情况是什么...”。在我们当前的项目设置中,更奇怪的是,我们在表中没有ID为1的存储:( core_store但设置脚本正在运行
David Manners 2014年

1
添加cms块应在数据存储区未锁定到Mage_Core_Model_App :: DISTRO_STORE_CODE的数据升级(而非安装)脚本中完成;更一般而言,安装脚本用于更改数据结构(并已锁定存储范围),而数据升级用于更改数据内容(并且可以在脚本期间更改存储范围)
Alessandro Ronchi 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.