O armazenamento atual é 1 ao executar scripts de atualização

15

Alguma idéia de por que Mage::app()->getStore()retorna a visualização da loja com o ID 1 quando dentro dos scripts de atualização independentes na visualização da loja em que estou executando o script de atualização (até mesmo o administrador)?
Quero dizer, eu sei onde está o código que faz isso. Em Mage_Core_Model_App::getStore()existe isto:

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

e _getDefaultStorefica assim:

   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 está sempre vazio ao alcançar o método acima.

Eu obtenho o mesmo resultado, mesmo que eu o adicione na parte superior do script de atualização:

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

Estou curioso sobre a lógica comercial de ter esse 'recurso'.

Marius
fonte
Eu pensei que os scripts de atualização estão sempre em execução no escopo do front-end. Freqüentemente digo aos scripts de atualização explicitamente para usar o repositório de administrador nas seguintes linhas.
bukart
@bukart. Tentei dizer explicitamente o script de atualização para executar a exibição do repositório de administradores, mas obtenho o mesmo resultado. Veja minhas últimas 3 linhas na pergunta.
Marius
Tentei responder à sua pergunta abaixo #
bukart

Respostas:

5

Nota: não esqueça que o escopo de armazenamento do administrador não está definido até que o despacho seja realizado e um estendido do controlador seja Mage_Adminhtml_Controller_Actionexecutado (consulte o adminhtml_controller_action_predispatch_startevento e o observador relacionado em Mage_Adminhtml_Controller_Action::preDispatch()).

Estou curioso sobre a lógica comercial de ter esse 'recurso'.

Você não é o único; Dito isto, podemos nunca saber, a menos que Moshe ou Dima desejem discutir.

Os scripts de instalação são executados no início da inicialização do aplicativo. O design disso provavelmente se deve a que, quando o restante da pilha for executado, as migrações necessárias e outro trabalho sejam "concluídos" - o que significa que o sistema estava pronto para uso imediato, mesmo quando um módulo estava sendo instalado ou atualizado. Gostaria de saber se os arquitetos originais inicialmente pensaram que seria necessário um sistema mais inicializado. Eu conjecturarei que, enquanto grande parte do código assume que existe uma instância de armazenamento disponível, a _getDefaultStore()lógica garante que exista uma instância de armazenamento.

As configurações completas do escopo estão disponíveis na 1.4.0.0 e posterior através de scripts de configuração de dados.

benmarks
fonte
3

Ok, para usar o repositório de administradores em seus scripts de atualização, basta usar

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

Sua abordagem Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID)); não pode ser bem-sucedida, pois não há uma visualização de armazenamento carregável realmente existente para o administrador

Muitas vezes eu uso um padrão como este:

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

Caso contrário, algumas vezes, após a execução de um script de atualização, os visitantes serão redirecionados para a página de administração, e não para o frontend às vezes.


Atualizar:

Eu interpretei mal a pergunta abaixo, então aqui está uma nova tentativa de explicar ^^

Os scripts de atualização são chamados de um método mais profundo no núcleo (Mage_Core_Model_Resource_Setup::_modifyResourceDb(...) )

Aqui eu tentei listar a pilha

  • 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)

e agora dê uma olhada em 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;
}

o método _initModules()é chamado antes de $scopeCodee $scopeTypeé determinado.

Atualmente, não consigo descobrir onde o fallback assumido está definido.

Bukart
fonte
Ah, mas há uma visualização da loja carregável para o administrador. dê uma olhada na core_storemesa. Há um registro com o ID 0. Além disso, se você tentar isso var_dump(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID)), receberá uma instância válida do repositório de administradores. Também tentei, Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);mas recebo o mesmo resultado. Mas minha pergunta não era sobre como definir o repositório de administradores em scripts de atualização. Eu estava perguntando por que Mage::app()->getStore()retorna a loja com o ID 1 nos scripts de atualização.
Marius
ah ... certo ... há um repositório de administradores no banco de dados, de fato.
bukart
11
Hmm ... eu conhecia a pilha, mas agora que a vi na sua resposta, ela me atingiu. As atualizações devem ser executadas de alguma forma 'sem estado'. Mas, para executar algo, você precisa de uma loja. Portanto, um valor padrão para a loja. Agora, a única coisa que não faz sentido é: Por que esse armazenamento padrão não é 0(admin) e é uma visualização de loja que pode ser facilmente excluída da interface do usuário do administrador? +1 por abrir os olhos. Se eu não receber outra resposta clara sobre isso, aceitarei isso.
Marius
mhh ... boa pergunta ... talvez depois do almoço eu dê uma olhada ... interessante ^^ #
bukart
A partir de 1.9.3.6, Mage::app()->getCurrentStore();não parece estar definido e gera um erro fatal quando chamado. Em vez disso, obtive o ID usando $currentStoreId = Mage::app()->getStore()->getId();.
Eric Seastrand
2

Portanto, a resposta básica é que ela realmente entra na terceira, se ..... espera o que :(

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

Para mim, retorna verdadeiro para Mage::isInstalled()e falso para o $this->getUpdateMode()que parece errado. Mas isso só acontece no primeiro hit degetStore .

Portanto, parece que ele configura a loja antes que o modo de atualização seja definido e, quando volta ao script de configuração, usa a chamada de loja padrão, usando o seguinte código:

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

O valor de self::DISTRO_STORE_ID é 1, acho que porque ele precisa de algo e não foi configurado para nós na loja do administrador :(

Na verdade, eu tenho um sistema que não armazena com o ID 1 e o script de atualização parece estar funcionando bem. Se estamos adicionando tabelas / atributos, tudo bem e mesmo ao adicionar um bloco cms específico do site, isso também está funcionando, mas obtemos todos os IDs da loja e os definimos especificamente ao salvar dados específicos da loja.

David Manners
fonte
Eu desenterrei a mesma coisa. O que eu não entendo é "Magento, por que você não usa o repositório de administradores para atualizações?". Parece mais razoável. Eu tenho medo de pensar o que acontece se eu excluir a loja com ID 1.
Marius
Ninguém seria suficiente louco para excluir o armazenamento de padrão;)
David Manners
Agora que sei disso, não ficarei louco, mas o fato de que é possível ... bem ... nunca confie em um usuário.
Marius
Um dos nossos PM me perguntou se ele poderia remover lojas antigas na semana passada. Acho que respondi com "O pior que poderia acontecer" .... e ainda mais estranho na configuração atual do projeto, não temos loja com o ID 1 :( na tabela, core_storemas os scripts de configuração estão funcionando
David Manners
11
a adição de um bloco cms deve ser feita em um script de atualização de dados (não instalação) em que o escopo da loja não esteja bloqueado no Mage_Core_Model_App :: DISTRO_STORE_CODE; mais em geral, instalar scripts são usados para a estrutura de dados de alteração (e têm escopo loja bloqueado) enquanto atualizar são usados para o conteúdo de dados de alteração de dados (e alcance loja pode ser alterado durante o script)
Alessandro Ronchi