🧩 Compatibilidad de modulos con multitienda
Actualizado: 2024-12-01
Un modulo compatible con multitienda guarda sus opciones por tienda cuando es necesario y funciona correctamente sea cual sea el contexto de Shop activo (tienda unica, grupo, todas las tiendas).
#Checklist de compatibilidad
| Item | Como verificar |
|---|---|
| Configuration usa id_shop | Configuration::get/updateValue respeta el contexto automaticamente |
| Tablas custom tienen id_shop | CREATE TABLE incluye id_shop INT + Shop::addSqlRestriction en queries |
| ObjectModel con multishop | En $definition: 'multishop' => true, campos con 'shop' => true |
| Hooks respetan el contexto | getContext()->shop->id usado en hooks que muestran contenido |
| Install registra en todas las tiendas | parent::install() ya lo hace, pero tablas custom deben replicarse |
| Formulario muestra contexto | El admin ve para que tienda/grupo esta editando |
#Configuracion por tienda en getContent()
Formulario de configuracion multitienda
php
<?php
public function getContent(): string
{
$output = '';
if (Tools::isSubmit('submit_' . $this->name)) {
// Configuration::updateValue guarda automaticamente
// para el contexto de tienda activo en el BO
Configuration::updateValue('MYMOD_TITLE', Tools::getValue('MYMOD_TITLE'));
Configuration::updateValue('MYMOD_ENABLED', (int) Tools::getValue('MYMOD_ENABLED'));
$output .= $this->displayConfirmation('Guardado correctamente');
}
// Mostrar indicador de contexto multitienda
if (Shop::isFeatureActive()) {
$shop = Context::getContext()->shop;
$output .= $this->displayInformation(
'Configurando para: <b>' . $shop->name . '</b> (ID: ' . $shop->id . ')'
);
if (Shop::getContext() === Shop::CONTEXT_ALL) {
$output .= $this->displayWarning(
'Estas editando la configuracion GLOBAL. Los valores se aplicaran a todas las tiendas que no tengan valor propio.'
);
}
}
return $output . $this->renderForm();
}
private function renderForm(): string
{
$fields = [
'form' => [
'legend' => ['title' => 'Configuracion'],
'input' => [
[
'type' => 'text',
'label' => 'Titulo',
'name' => 'MYMOD_TITLE',
'desc' => 'Titulo mostrado en el front',
],
[
'type' => 'switch',
'label' => 'Activar',
'name' => 'MYMOD_ENABLED',
'values' => [
['id' => 'on', 'value' => 1, 'label' => 'Si'],
['id' => 'off', 'value' => 0, 'label' => 'No'],
],
],
],
'submit' => ['title' => 'Guardar'],
],
];
$helper = new HelperForm();
$helper->submit_action = 'submit_' . $this->name;
$helper->fields_value = [
'MYMOD_TITLE' => Configuration::get('MYMOD_TITLE'),
'MYMOD_ENABLED' => Configuration::get('MYMOD_ENABLED'),
];
return $helper->generateForm([$fields]);
}
#Install y uninstall multitienda
Install compatible con multitienda
php
<?php
public function install(): bool
{
// parent::install() ya registra el modulo en todas las tiendas activas
if (!parent::install()) {
return false;
}
// Crear tabla con id_shop
$sql = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'mymodule_data` (
`id_mymodule_data` INT UNSIGNED AUTO_INCREMENT,
`id_shop` INT UNSIGNED NOT NULL DEFAULT 1,
`value` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id_mymodule_data`),
KEY `idx_shop` (`id_shop`)
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4';
if (!Db::getInstance()->execute($sql)) {
return false;
}
// Insertar configuracion por defecto para CADA tienda
if (Shop::isFeatureActive()) {
$shops = Shop::getShops(true, null, true); // IDs de tiendas activas
foreach ($shops as $idShop) {
Configuration::updateValue('MYMOD_ENABLED', 1, false, null, $idShop);
Configuration::updateValue('MYMOD_TITLE', 'Default', false, null, $idShop);
}
} else {
Configuration::updateValue('MYMOD_ENABLED', 1);
Configuration::updateValue('MYMOD_TITLE', 'Default');
}
return true;
}
public function uninstall(): bool
{
// Limpiar configuracion de TODAS las tiendas
Configuration::deleteByName('MYMOD_ENABLED');
Configuration::deleteByName('MYMOD_TITLE');
Db::getInstance()->execute(
'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'mymodule_data`'
);
return parent::uninstall();
}
#Errores comunes
| Error | Causa | Solucion |
|---|---|---|
| Configuracion se pierde al cambiar de tienda | updateValue sin contexto correcto | Verificar Shop::getContext() antes de guardar |
| Datos duplicados entre tiendas | INSERT sin id_shop | Añadir id_shop a la tabla y filtrar en queries |
| Modulo no aparece en tienda 2 | No instalado en esa tienda | BO → Modulos → Filtrar por tienda → Instalar |
| Hook se ejecuta en tienda equivocada | No filtra por contexto en el hook | Verificar Context::getContext()->shop->id |
| Query devuelve datos de todas las tiendas | Falta Shop::addSqlRestriction | Añadir filtro de tienda a todas las queries |
Descargar en Markdown
Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.