La tienda actual es 1 cuando ejecuta scripts de actualización

15

¿Alguna idea de por qué Mage::app()->getStore()devuelve la vista de la tienda con el ID 1 cuando está dentro de los scripts de actualización independientes de la vista de la tienda en la que estoy ejecutando el script de actualización (incluso el administrador)?
Quiero decir, sé dónde está el código que hace esto. En Mage_Core_Model_App::getStore()está esto:

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

y se _getDefaultStoreve así:

   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 siempre está vacío cuando se llega al método anterior.

Obtengo el mismo resultado incluso si agrego esto en la parte superior del script de actualización:

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

Tengo curiosidad sobre la lógica empresarial de tener esta 'característica'.

Marius
fuente
Pensé que los scripts de actualización siempre se ejecutan en el ámbito de la interfaz. A menudo les digo explícitamente a los scripts de actualización que usen el almacén de administración para las siguientes líneas.
bukart
@bukart. Intenté decirle explícitamente al script de actualización que ejecute la vista de la tienda de administración, pero obtengo el mismo resultado. Vea mis últimas 3 líneas en la pregunta.
Marius
Traté de responder tu pregunta a continuación
bukart

Respuestas:

5

NB: no olvide que el alcance de la tienda de administración no se establece hasta que se realiza el despacho y se Mage_Adminhtml_Controller_Actionejecuta un controlador que se extiende (consulte el adminhtml_controller_action_predispatch_startevento y el observador relacionado en Mage_Adminhtml_Controller_Action::preDispatch()).

Tengo curiosidad sobre la lógica empresarial de tener esta 'característica'.

No eres el único; Dicho esto, es posible que nunca lo sepamos a menos que Moshe o Dima quieran discutir.

Los scripts de instalación se ejecutan temprano en la inicialización de la aplicación. El diseño de esto probablemente se deba a que, para cuando se ejecute el resto de la pila, se realizarán las migraciones necesarias y otros trabajos, lo que significa que el sistema estaba listo para usar de inmediato, incluso cuando se estaba instalando un módulo o actualizado. Me pregunto si los arquitectos originales inicialmente alguna vez pensaron que sería necesario un sistema más inicializado. Supondré que, si bien gran parte del código supone que hay una instancia de tienda disponible, la _getDefaultStore()lógica garantiza que haya una instancia de tienda.

La configuración de alcance total está disponible en 1.4.0.0 y versiones posteriores mediante scripts de configuración de datos.

puntos de referencia
fuente
3

Ok, para usar la tienda de administración en tus scripts de actualización solo usa

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

Su enfoque Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID)); no puede tener éxito, porque no hay realmente una vista de tienda cargable para el administrador

A menudo uso un patrón 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());

De lo contrario, a veces, después de ejecutar un script de actualización, sus visitantes serán redirigidos a la página de administración en lugar de a la interfaz.


Actualizar:

Interpreté mal la pregunta a continuación, así que aquí hay un nuevo intento de explicar ^^

Los scripts de actualización se invocan desde un método más profundo en el núcleo ( Mage_Core_Model_Resource_Setup::_modifyResourceDb(...))

Aquí intenté enumerar la pila

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

y ahora echa un vistazo a 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;
}

el método _initModules()se llama antes $scopeCodey $scopeTypese determina el.

Actualmente no puedo entender dónde se define el retroceso supuesto.

bukart
fuente
Ah, pero hay una vista de tienda cargable para el administrador. echa un vistazo en la core_storemesa. Hay un registro con id 0. Además, si intenta esto var_dump(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID)), obtendrá una instancia válida de la tienda de administración. También lo intenté Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);pero obtengo el mismo resultado. Pero mi pregunta no era sobre cómo configurar la tienda de administración en los scripts de actualización. Estaba preguntando por qué Mage::app()->getStore()devuelve la tienda con id 1 en los scripts de actualización.
Marius
oh ... claro ... hay una tienda de administración en la base de datos, de hecho.
bukart
1
Hmm ... conocía la pila, pero ahora que la he visto en tu respuesta me golpeó. Las actualizaciones deberían ejecutarse de alguna manera 'sin estado'. Pero para ejecutar algo necesitas una tienda. De ahí un valor predeterminado para la tienda. Ahora, lo único que no tiene sentido es: ¿Por qué esta tienda predeterminada no es 0(admin) y es una vista de tienda que podría eliminarse fácilmente de la interfaz de usuario de administrador? +1 por abrir mis ojos. Si no obtengo otra respuesta clara sobre esto, aceptaré esto.
Marius
mhh ... buena pregunta ... tal vez después del almuerzo echaré un vistazo ... interesante ^^
bukart
A partir de 1.9.3.6, Mage::app()->getCurrentStore();no parece estar definido y da un error fatal cuando se llama. En cambio, obtuve la identificación usando $currentStoreId = Mage::app()->getStore()->getId();.
Eric Seastrand
2

Entonces, la respuesta básica es que realmente se mete en el 3er si ..... espere qué :(

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

Para mí, devuelve verdadero para Mage::isInstalled()y falso para lo $this->getUpdateMode()que suena mal. Pero esto solo ocurre en el primer golpe de getStore.

Por lo tanto, parece que configura la tienda antes de que se haya configurado el modo de actualización, luego, cuando regresa en el script de configuración, usa la llamada de tienda predeterminada que usa el siguiente código:

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

El valor de self::DISTRO_STORE_IDes 1, supongo porque necesita algo y no se configuró para nosotros en la tienda de administración :(

Así que en realidad tengo un sistema que no se ha almacenado con la identificación 1 y parece que el script de actualización funciona bien. Si estamos agregando tablas / atributos, está bien e incluso al agregar un bloque de cms específico del sitio, esto también está funcionando, pero obtenemos toda la identificación de la tienda y los configuramos específicamente al guardar datos específicos de la tienda.

David modales
fuente
Desenterré lo mismo. Lo que no entiendo es "Magento, ¿por qué no usas la tienda de administración para las actualizaciones?". Parece más razonable. Me da miedo pensar qué sucede si elimino la tienda con la identificación 1.
Marius
Nadie estaría lo suficientemente loco como para eliminar la tienda predeterminada;)
David Manners
Ahora que sé esto, no estaré loco, pero el hecho de que sea posible ... bueno ... nunca confíes en un usuario.
Marius
Uno de nuestros PM me preguntó si podía eliminar las tiendas viejas la semana pasada. Creo que respondí con "¿Qué es lo peor que podría pasar?" ... y aún más extraño en nuestra configuración actual del proyecto, no tenemos una tienda con id 1 :( en la tabla, core_storepero los scripts de configuración funcionan
David Manners
1
la adición de un bloque cms debe realizarse en un script de actualización de datos (no de instalación) donde el alcance de la tienda no está bloqueado en Mage_Core_Model_App :: DISTRO_STORE_CODE; más en general, los scripts de instalación se usan para cambiar la estructura de datos (y tienen el alcance de la tienda bloqueado) mientras que la actualización de datos se usa para cambiar el contenido de los datos (y el alcance de la tienda se puede cambiar durante el script)
Alessandro Ronchi