📝 HelperForm con tabs — ejemplo real ecom_stickycart

Actualizado: 2024-12-01
💡
Codigo real de produccion

Este ejemplo esta extraido del modulo ecom_stickycart (Sticky Add to Cart Pro), un modulo real en produccion. No es codigo de tutorial: es codigo que funciona en tiendas reales.

#Que hace este modulo

ecom_stickycart muestra una barra sticky de 'Añadir al carrito' en la pagina de producto. El admin puede configurar layout, colores, animacion, posicion y funcionalidades desde el BO usando un formulario HelperForm con tabs.

#Constructor y install

Constructor con $this->trans() y install con hooks
php
<?php
class Ecom_stickycart extends Module
{
    public function __construct()
    {
        $this->name = 'ecom_stickycart';
        $this->tab = 'front_office_features';
        $this->version = '2.0.0';
        $this->author = 'Ecom Experts';
        $this->need_instance = 0;
        $this->ps_versions_compliancy = ['min' => '1.7', 'max' => _PS_VERSION_];
        $this->bootstrap = true;

        parent::__construct();

        // Usar $this->trans() con dominio para sistema moderno de traducciones
        $this->displayName = $this->trans(
            'Sticky Add to Cart Pro', [], 'Modules.Ecomstickycart.Admin'
        );
        $this->description = $this->trans(
            'Professional sticky add to cart bar.', [], 'Modules.Ecomstickycart.Admin'
        );
    }

    // Necesario para que PS use archivos .xlf en lugar de legacy
    public function isUsingNewTranslationSystem()
    {
        return true;
    }

    public function install()
    {
        return parent::install()
            && $this->registerHook('displayHeader')
            && $this->registerHook('displayFooter')
            && $this->registerHook('displayBackOfficeHeader')
            && $this->registerHook('actionFrontControllerSetMedia')
            && $this->setConfigDefaults();
    }

    // Valores por defecto separados en metodo propio (buena practica)
    protected function setConfigDefaults()
    {
        $defaults = [
            'ECOM_STICKY_LAYOUT'        => 'classic',
            'ECOM_STICKY_BG_COLOR'      => '#ffffff',
            'ECOM_STICKY_TXT_COLOR'     => '#333333',
            'ECOM_STICKY_BTN_COLOR'     => '#2fb5d2',
            'ECOM_STICKY_POSITION'      => 'bottom',
            'ECOM_STICKY_SCROLL_TRIGGER' => '300',
            'ECOM_STICKY_ANIMATION'     => 'fade',
            'ECOM_STICKY_SHOW_QTY'      => '1',
            'ECOM_STICKY_MOBILE_OPTIMIZED' => '1',
            'ECOM_STICKY_CUSTOM_CSS'    => '',
        ];
        foreach ($defaults as $key => $value) {
            Configuration::updateValue($key, $value);
        }
        return true;
    }
}

#getContent — procesar formulario

Patron clasico: isSubmit → process → display
php
<?php
public function getContent()
{
    $output = '';

    // Guardar configuracion
    if (Tools::isSubmit('submitEcomStickyCart')) {
        $this->processConfiguration();
        $output .= $this->displayConfirmation(
            $this->trans('Settings updated successfully.', [], 'Admin.Global')
        );
    }

    // Boton de reset a valores por defecto
    if (Tools::isSubmit('submitEcomStickyCartReset')) {
        $this->setConfigDefaults();
        $output .= $this->displayConfirmation(
            $this->trans('Settings reset to defaults.', [], 'Admin.Global')
        );
    }

    return $output . $this->renderForm();
}

protected function processConfiguration()
{
    $configs = [
        'ECOM_STICKY_LAYOUT', 'ECOM_STICKY_BG_COLOR',
        'ECOM_STICKY_TXT_COLOR', 'ECOM_STICKY_BTN_COLOR',
        'ECOM_STICKY_POSITION', 'ECOM_STICKY_SCROLL_TRIGGER',
        'ECOM_STICKY_ANIMATION', 'ECOM_STICKY_SHOW_QTY',
        'ECOM_STICKY_MOBILE_OPTIMIZED', 'ECOM_STICKY_CUSTOM_CSS',
    ];

    foreach ($configs as $config) {
        $value = Tools::getValue($config);
        // Castear valores numericos
        if ($config === 'ECOM_STICKY_SCROLL_TRIGGER') {
            $value = (int) $value;
        }
        Configuration::updateValue($config, $value);
    }

    // Caso especial: select multiple devuelve array
    $excludeCategories = Tools::getValue('ECOM_STICKY_EXCLUDE_CATEGORIES');
    if (is_array($excludeCategories)) {
        Configuration::updateValue(
            'ECOM_STICKY_EXCLUDE_CATEGORIES',
            implode(',', array_map('intval', $excludeCategories))
        );
    } else {
        Configuration::updateValue('ECOM_STICKY_EXCLUDE_CATEGORIES', '');
    }
}

#renderForm — HelperForm completo

HelperForm con tabs, color, select, switch y multiple
php
<?php
protected function renderForm()
{
    // Preparar opciones de categorias para el select multiple
    $categories = Category::getSimpleCategories($this->context->language->id);
    $categoryOptions = [];
    foreach ($categories as $cat) {
        $categoryOptions[] = ['id' => $cat['id_category'], 'name' => $cat['name']];
    }

    $fields_form = [
        'form' => [
            'legend' => [
                'title' => $this->trans('Sticky Cart Configuration', [], 'Modules.Ecomstickycart.Admin'),
                'icon' => 'icon-cogs',
            ],
            // ══ TABS: Agrupan campos visualmente ══
            'tabs' => [
                'general'  => 'General Settings',
                'visual'   => 'Visual Settings',
                'features' => 'Feature Settings',
            ],
            'input' => [
                // ── TAB GENERAL: select, text ──
                [
                    'type' => 'select',
                    'label' => 'Layout',
                    'name' => 'ECOM_STICKY_LAYOUT',
                    'tab' => 'general',       // ← Asigna al tab
                    'options' => [
                        'query' => [
                            ['id' => 'classic', 'name' => 'Classic Bar'],
                            ['id' => 'minimal', 'name' => 'Minimal (Floating)'],
                            ['id' => 'modern',  'name' => 'Modern (Glassmorphism)'],
                        ],
                        'id' => 'id', 'name' => 'name',
                    ],
                ],
                [
                    'type' => 'text',
                    'label' => 'Scroll Trigger (px)',
                    'name' => 'ECOM_STICKY_SCROLL_TRIGGER',
                    'tab' => 'general',
                    'desc' => 'How far to scroll before showing the sticky cart.',
                    'col' => 2,               // ← Ancho de columna
                ],

                // ── TAB VISUAL: color, textarea ──
                [
                    'type' => 'color',         // ← Color picker nativo
                    'label' => 'Background Color',
                    'name' => 'ECOM_STICKY_BG_COLOR',
                    'tab' => 'visual',
                ],
                [
                    'type' => 'color',
                    'label' => 'Button Color',
                    'name' => 'ECOM_STICKY_BTN_COLOR',
                    'tab' => 'visual',
                ],
                [
                    'type' => 'textarea',
                    'label' => 'Custom CSS',
                    'name' => 'ECOM_STICKY_CUSTOM_CSS',
                    'tab' => 'visual',
                    'col' => 9, 'rows' => 5,
                ],

                // ── TAB FEATURES: switch, select multiple ──
                [
                    'type' => 'switch',        // ← Toggle on/off
                    'label' => 'Show Quantity Selector',
                    'name' => 'ECOM_STICKY_SHOW_QTY',
                    'tab' => 'features',
                    'is_bool' => true,
                    'values' => [
                        ['id' => 'active_on',  'value' => 1, 'label' => 'Yes'],
                        ['id' => 'active_off', 'value' => 0, 'label' => 'No'],
                    ],
                ],
                [
                    'type' => 'select',
                    'label' => 'Exclude Categories',
                    'name' => 'ECOM_STICKY_EXCLUDE_CATEGORIES[]', // ← [] para multiple
                    'tab' => 'features',
                    'class' => 'chosen',       // ← Plugin chosen.js
                    'multiple' => true,        // ← Select multiple
                    'options' => [
                        'query' => $categoryOptions,
                        'id' => 'id', 'name' => 'name',
                    ],
                ],
            ],
            'submit' => ['title' => 'Save'],
        ],
    ];

    // ── Configurar el HelperForm ──
    $helper = new HelperForm();
    $helper->show_toolbar = false;
    $helper->table = $this->table;
    $helper->module = $this;
    $helper->default_form_language = $this->context->language->id;
    $helper->identifier = $this->identifier;
    $helper->submit_action = 'submitEcomStickyCart';
    $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false)
        . '&configure=' . $this->name
        . '&tab_module=' . $this->tab
        . '&module_name=' . $this->name;
    $helper->token = Tools::getAdminTokenLite('AdminModules');
    $helper->tpl_vars = [
        'fields_value' => $this->getConfigFieldsValues(),
    ];

    return $helper->generateForm([$fields_form]);
}

#getConfigFieldsValues

Devolver valores actuales para los campos
php
<?php
protected function getConfigFieldsValues()
{
    // Caso especial: categorias excluidas guardadas como string "1,2,3"
    // Necesita convertirse a array para el select multiple
    $excludeStr = Configuration::get('ECOM_STICKY_EXCLUDE_CATEGORIES');
    $excludeArr = !empty($excludeStr) ? explode(',', $excludeStr) : [];

    return [
        'ECOM_STICKY_LAYOUT'        => Configuration::get('ECOM_STICKY_LAYOUT'),
        'ECOM_STICKY_BG_COLOR'      => Configuration::get('ECOM_STICKY_BG_COLOR'),
        'ECOM_STICKY_TXT_COLOR'     => Configuration::get('ECOM_STICKY_TXT_COLOR'),
        'ECOM_STICKY_BTN_COLOR'     => Configuration::get('ECOM_STICKY_BTN_COLOR'),
        'ECOM_STICKY_POSITION'      => Configuration::get('ECOM_STICKY_POSITION'),
        'ECOM_STICKY_SCROLL_TRIGGER' => Configuration::get('ECOM_STICKY_SCROLL_TRIGGER'),
        'ECOM_STICKY_ANIMATION'     => Configuration::get('ECOM_STICKY_ANIMATION'),
        'ECOM_STICKY_SHOW_QTY'      => Configuration::get('ECOM_STICKY_SHOW_QTY'),
        'ECOM_STICKY_MOBILE_OPTIMIZED' => Configuration::get('ECOM_STICKY_MOBILE_OPTIMIZED'),
        'ECOM_STICKY_CUSTOM_CSS'    => Configuration::get('ECOM_STICKY_CUSTOM_CSS'),
        // ¡OJO! El nombre incluye [] para select multiple
        'ECOM_STICKY_EXCLUDE_CATEGORIES[]' => $excludeArr,
    ];
}

#Patrones a destacar

PatronDonde se usaPor que es buena practica
Tabs en HelperForm'tabs' => ['general' => ..., 'visual' => ...]Agrupa opciones, mejor UX cuando hay muchos campos
setConfigDefaults()install() y boton resetMetodo separado reutilizable, no repite codigo
Color picker'type' => 'color'Nativo de PS, no necesita JS extra
Select multiple + chosen'multiple' => true, 'class' => 'chosen'UX de busqueda en select con muchas opciones
Cast (int) en process$value = (int) $valueSanitizar valores numericos antes de guardar
isUsingNewTranslationSystem()return trueActiva sistema .xlf moderno (PS 1.7.6+)
Array a string para Configurationimplode(',', array_map('intval', ...))Configuration::updateValue solo guarda strings
Descargar en Markdown Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.