🔍 Queries y datos en multitienda
Actualizado: 2024-12-01
En multitienda, cada query debe considerar el contexto de tienda. Un modulo que funciona en tienda unica puede fallar en multitienda si no filtra correctamente por id_shop.
#Configuration en multitienda
Leer y escribir configuracion por tienda
php
<?php
// ── Configuration::get() respeta el contexto de tienda automaticamente ──
$valor = Configuration::get('MI_MODULO_OPCION');
// Busca en: tienda actual → grupo de tiendas → global
// ── Leer valor de una tienda especifica ──
$valorTienda2 = Configuration::get('MI_MODULO_OPCION', null, null, 2);
// Firma: get($key, $id_lang = null, $id_shop_group = null, $id_shop = null)
// ── Escribir valor para la tienda actual ──
Configuration::updateValue('MI_MODULO_OPCION', 'valor');
// Guarda en ps_configuration con id_shop = tienda actual
// ── Escribir valor global (todas las tiendas) ──
Configuration::updateGlobalValue('MI_MODULO_OPCION', 'valor_global');
// id_shop = 0, id_shop_group = 0
// ── Escribir valor para tienda especifica ──
$oldShop = Shop::getContext();
Shop::setContext(Shop::CONTEXT_SHOP, 2);
Configuration::updateValue('MI_MODULO_OPCION', 'valor_tienda_2');
Shop::setContext($oldShop);
// ── Eliminar configuracion por tienda ──
Configuration::deleteByName('MI_MODULO_OPCION');
// Elimina de TODAS las tiendas
#ObjectModel y id_shop
ObjectModel en contexto multitienda
php
<?php
// ── ObjectModel con multishop ──
// En la definicion de la clase:
class MyEntity extends ObjectModel
{
public static $definition = [
'table' => 'mymodule_entity',
'primary' => 'id_mymodule_entity',
'multilang' => true,
'multishop' => true, // ← Habilitar multitienda
'fields' => [
'active' => ['type' => self::TYPE_BOOL, 'shop' => true],
// 'shop' => true → este campo se guarda POR tienda
// 'shop' => false o ausente → campo global
'name' => ['type' => self::TYPE_STRING, 'lang' => true, 'shop' => true],
'config' => ['type' => self::TYPE_STRING, 'shop' => false], // Global
],
];
}
// Cuando multishop = true, PS crea automaticamente:
// ps_mymodule_entity (datos globales)
// ps_mymodule_entity_shop (datos por tienda)
// ps_mymodule_entity_lang (si multilang)
// ── Guardar asociacion con tienda ──
$entity = new MyEntity();
$entity->active = true;
$entity->name = 'Mi entidad';
$entity->id_shop_list = [1, 2]; // Asociar a tiendas 1 y 2
$entity->add();
// ── Leer filtrando por tienda ──
$entity = new MyEntity($id); // Usa la tienda actual del contexto
#Queries con filtro de tienda
Filtrar queries por id_shop
php
<?php
// ── Obtener id_shop actual ──
$idShop = (int) Context::getContext()->shop->id;
// ── Query filtrada por tienda ──
$results = Db::getInstance()->executeS(
(new DbQuery())
->select('e.*, es.active')
->from('mymodule_entity', 'e')
->innerJoin('mymodule_entity_shop', 'es',
'e.id_mymodule_entity = es.id_mymodule_entity AND es.id_shop = ' . $idShop)
->where('es.active = 1')
->orderBy('e.position ASC')
);
// ── Con Shop::addSqlRestriction (metodo recomendado) ──
$sql = 'SELECT p.*, ps.active, ps.price
FROM `' . _DB_PREFIX_ . 'product` p
' . Shop::addSqlAssociation('product', 'p') . '
WHERE ps.active = 1';
// addSqlAssociation genera:
// INNER JOIN ps_product_shop ps ON p.id_product = ps.id_product
// AND ps.id_shop IN (tiendas del contexto actual)
// ── Para tablas custom, usar Shop::addSqlRestriction ──
$sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'mymodule_data` md
WHERE 1 ' . Shop::addSqlRestriction(false, 'md');
// Añade: AND md.id_shop = X (o IN (X, Y) segun contexto)
#Datos compartidos vs por tienda
| Dato | Compartido | Por tienda | Recomendacion |
|---|---|---|---|
| Producto (base) | Si | Precio, stock, activo | Crear producto una vez, personalizar por tienda |
| Categoria | Si (estructura) | Nombre, desc, activo | Misma estructura, contenido diferente |
| Cliente | Configurable | Configurable | Compartir clientes entre tiendas es lo habitual |
| Pedido | No | Si (pertenece a una tienda) | Cada pedido es de una tienda especifica |
| Transportista | No | Si | Diferentes transportistas por tienda |
| CMS Page | Si (ID) | Contenido por tienda | Misma pagina, diferente contenido |
| Modulo config | Depende | Depende | Usar Configuration con id_shop |
Descargar en Markdown
Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.