🔷 ObjectModel — Referencia completa

Actualizado: 2024-12-01

ObjectModel es la capa de abstraccion de base de datos propia de PrestaShop. Define la estructura de las tablas, las validaciones y las operaciones CRUD de forma declarativa mediante el array $definition.

#La propiedad $definition

Estructura completa de $definition
php
<?php

class MyEntity extends ObjectModel
{
    // ── Propiedades publicas (una por cada campo en DB) ──
    public $name;          // campo multilang
    public $description;   // campo multilang
    public $active;
    public $price;
    public $sort_order;
    public $id_category;   // FK a otra tabla
    public $date_add;
    public $date_upd;

    public static $definition = [
        'table'          => 'mymodule_entity',     // Nombre sin prefijo
        'primary'        => 'id_mymodule_entity',  // Clave primaria
        'multilang'      => true,  // true = tabla _lang para campos con 'lang'=>true
        'multilang_shop' => false, // true = tabla _lang_shop (multilang + multitienda)
        'multishop'      => false, // true = tabla _shop para datos por tienda
        'fields' => [
            // ── Campos simples ──
            'active'      => ['type' => self::TYPE_BOOL,   'validate' => 'isBool'],
            'price'       => ['type' => self::TYPE_FLOAT,  'validate' => 'isPrice', 'shop' => true],
            'sort_order'  => ['type' => self::TYPE_INT,    'validate' => 'isUnsignedInt', 'default' => 0],
            'id_category' => ['type' => self::TYPE_INT,    'validate' => 'isUnsignedId'],
            'date_add'    => ['type' => self::TYPE_DATE,   'validate' => 'isDate'],
            'date_upd'    => ['type' => self::TYPE_DATE,   'validate' => 'isDate'],

            // ── Campos multiidioma (van a tabla _lang) ──
            'name' => [
                'type'     => self::TYPE_STRING,
                'lang'     => true,
                'validate' => 'isCatalogName',
                'required' => true,
                'size'     => 255,
            ],
            'description' => [
                'type'       => self::TYPE_HTML,
                'lang'       => true,
                'validate'   => 'isCleanHtml',
                'allow_html' => true,
            ],
        ],
    ];
}

#Tipos de campo disponibles

ConstantePHP TypeDescripcion
TYPE_INTintEntero (incluye negativos)
TYPE_UINTintEntero sin signo (>=0)
TYPE_BOOLboolBooleano (0 o 1)
TYPE_STRINGstringTexto plano (se escapa)
TYPE_HTMLstringHTML (se usa isCleanHtml)
TYPE_FLOATfloatNumero decimal
TYPE_DATEstringFecha formato Y-m-d H:i:s
TYPE_NOTHING-Campo sin mapeo especial

#Campos multiidioma

Crear tabla principal y tabla _lang
php
<?php

// ── SQL para tabla principal ──
CREATE TABLE IF NOT EXISTS `ps_mymodule_entity` (
    `id_mymodule_entity` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `id_category` int(10) unsigned NOT NULL DEFAULT 0,
    `active` tinyint(1) unsigned NOT NULL DEFAULT 1,
    `price` decimal(20,6) NOT NULL DEFAULT 0.000000,
    `sort_order` int(10) unsigned NOT NULL DEFAULT 0,
    `date_add` datetime NOT NULL,
    `date_upd` datetime NOT NULL,
    PRIMARY KEY (`id_mymodule_entity`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

// ── SQL para tabla _lang (campos multiidioma) ──
CREATE TABLE IF NOT EXISTS `ps_mymodule_entity_lang` (
    `id_mymodule_entity` int(10) unsigned NOT NULL,
    `id_lang` int(10) unsigned NOT NULL,
    `id_shop` int(10) unsigned NOT NULL DEFAULT 1,
    `name` varchar(255) NOT NULL,
    `description` text,
    PRIMARY KEY (`id_mymodule_entity`, `id_lang`, `id_shop`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

// ── Usar multilang en PHP ──
$entity = new MyEntity();
$entity->name = [
    1 => 'Nombre en espanol',  // id_lang => valor
    2 => 'Name in English',
];
$entity->description[1] = '<p>Descripcion en espanol</p>';
$entity->active = true;
$entity->add();

// ── Leer con idioma especifico ──
$entity = new MyEntity(42, $id_lang);  // Carga el objeto con el idioma dado
echo $entity->name; // 'Nombre en espanol' si id_lang = 1

#Operaciones CRUD

CRUD completo con ObjectModel
php
<?php

// ── CREATE ──
$entity = new MyEntity();
$entity->name   = [1 => 'Test', 2 => 'Test EN'];
$entity->active = true;
$entity->price  = 19.99;
$result = $entity->add(); // bool
$newId  = $entity->id;   // ID insertado

// ── READ ──
$entity = new MyEntity(42);           // Carga por ID (sin idioma)
$entity = new MyEntity(42, $id_lang); // Carga por ID con idioma

// Verificar que se cargo correctamente:
if (!Validate::isLoadedObject($entity)) {
    throw new \Exception('Entity not found');
}

// ── UPDATE ──
$entity = new MyEntity(42, $id_lang);
$entity->price  = 24.99;
$entity->active = false;
$result = $entity->update(); // bool

// ── DELETE ──
$entity = new MyEntity(42);
$result = $entity->delete(); // bool

// ── Soft delete (marcar como inactivo) ──
$entity->active = 0;
$entity->update();

// ── Comprobar existencia ──
$exists = MyEntity::existsInDatabase(42, 'mymodule_entity'); // bool

#Validaciones de campo

Validate::Descripcion
isName($s)Nombre personal (letras, espacios, guiones)
isCatalogName($s)Nombre de catalogo (mas permisivo)
isGenericName($s)Nombre generico
isCleanHtml($s)HTML limpio (sin scripts)
isUnsignedId($n)ID positivo
isUnsignedInt($n)Entero positivo
isPrice($f)Precio (decimal positivo)
isDate($d)Fecha formato Y-m-d
isEmail($e)Email valido
isUrl($u)URL valida
isMd5($s)Hash MD5 valido
isBool($b)0 o 1
isColor($s)Color hexadecimal #RRGGBB
isAbsoluteUrl($u)URL absoluta con protocolo

#Metodos de busqueda

Metodos estaticos de busqueda en ObjectModel
php
<?php

// ── getAll(): todos los registros ──
// No existe por defecto — hay que implementarlo:
public static function getAll(int $idLang = 0, bool $activeOnly = false): array
{
    $q = new DbQuery();
    $q->select('e.*, el.name, el.description');
    $q->from('mymodule_entity', 'e');
    if ($idLang) {
        $q->leftJoin('mymodule_entity_lang', 'el',
            'e.id_mymodule_entity = el.id_mymodule_entity AND el.id_lang = ' . (int) $idLang
        );
    }
    if ($activeOnly) {
        $q->where('e.active = 1');
    }
    $q->orderBy('e.sort_order ASC, e.date_add DESC');
    return Db::getInstance()->executeS($q) ?: [];
}

// ── Busqueda por campo especifico ──
public static function getByCategory(int $idCategory, int $idLang): array
{
    return Db::getInstance()->executeS(
        (new DbQuery())
            ->select('e.*, el.name')
            ->from('mymodule_entity', 'e')
            ->innerJoin('mymodule_entity_lang', 'el',
                'e.id_mymodule_entity = el.id_mymodule_entity AND el.id_lang = ' . (int) $idLang
            )
            ->where('e.id_category = ' . (int) $idCategory)
            ->where('e.active = 1')
    ) ?: [];
}

#Multitienda

ObjectModel con soporte multitienda
php
<?php

// En $definition:
'multishop' => true,  // Activa tabla _shop

// Esto crea una tabla ps_mymodule_entity_shop con:
// (id_mymodule_entity, id_shop) + los campos marcados con 'shop' => true

// Campos que se pueden sobreescribir por tienda:
'price' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'shop' => true],

// ── Leer datos de la tienda actual ──
Shop::addTableAssociation('mymodule_entity', ['type' => 'shop']);

$entity = new MyEntity(42);
// Si multishop activo, carga automaticamente los datos de Context::shop

// ── Actualizar para una tienda especifica ──
$entity = new MyEntity(42);
$entity->price = 15.99;
$entity->setFieldsToUpdate(['price' => true]); // Solo actualiza este campo
$entity->update();
Descargar en Markdown Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.