Buenas practicas para modulos PrestaShop

Actualizado: 2024-12-01

Desarrollar modulos de calidad para PrestaShop requiere seguir una serie de buenas practicas que garantizan seguridad, rendimiento y compatibilidad. Esta guia resume los puntos mas importantes del desarrollo profesional de modulos.

#Seguridad obligatoria

Reglas de seguridad en todos los archivos PHP
php
<?php

// 1. OBLIGATORIO en todos los archivos PHP del modulo
if (!defined('_PS_VERSION_')) { exit; }

// 2. Sanitizar SIEMPRE las entradas del usuario
$name    = pSQL(Tools::getValue('name', ''));         // escape para SQL
$idItem  = (int) Tools::getValue('id_item', 0);      // cast a int
$html    = Tools::purifyHTML(Tools::getValue('desc')); // sanitizar HTML
$text    = htmlspecialchars(Tools::getValue('text')); // escape HTML

// 3. Usar siempre parametros preparados o escape de DB
Db::getInstance()->insert('mytable', [
    'name'  => pSQL($name),        // BIEN
    'price' => (float) $price,     // BIEN
]);

// MAL — vulnerable a SQL injection:
// Db::getInstance()->execute('SELECT * FROM mytable WHERE name = \'' . $_GET['name'] . '\'');

// BIEN — con escape:
Db::getInstance()->execute(
    'SELECT * FROM `' . _DB_PREFIX_ . 'mytable`
     WHERE name = \'' . pSQL($_GET['name']) . '\''
);

// 4. Verificar tokens en formularios del BO
if (Tools::isSubmit('submitMyForm') && !Tools::checkToken()) {
    die('Invalid token');
}

// 5. Permisos en AdminControllers
public function initContent(): void
{
    if (!$this->access('view')) {
        Tools::redirectAdmin(self::$currentIndex . '&token=' . $this->token);
    }
}

#Rendimiento

PracticaImpactoComo implementar
Cachear queries pesadasAltoCache::getInstance()->remember()
Usar indices en columnas de busquedaAltoADD INDEX en install()
Evitar N+1 queries en hooksAltoUna sola query con JOIN
Cargar CSS/JS solo cuando se necesitanMedioVerificar $controller->php_self
Usar LazyLoad en imagenes del moduloMedioloading='lazy' en
No hacer peticiones HTTP en hooks syncAltoUsar jobs/cron en lugar de peticiones en hooks

#Instalacion y desinstalacion limpias

install() y uninstall() completos y limpios
php
<?php

public function install(): bool
{
    // Orden: padre primero, luego tabla, luego hooks
    return parent::install()
        && $this->createTable()
        && $this->registerHook('displayHeader')
        && $this->registerHook('actionOrderStatusUpdate');
}

public function uninstall(): bool
{
    // Limpiar TODO lo creado por el modulo
    return $this->dropTable()
        && $this->cleanConfiguration()
        && parent::uninstall();
}

private function createTable(): bool
{
    return Db::getInstance()->execute(
        'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'mymodule_data` (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `value` varchar(255) NOT NULL,
            PRIMARY KEY (`id`)
        ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4'
    );
}

private function dropTable(): bool
{
    return Db::getInstance()->execute(
        'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'mymodule_data`'
    );
}

private function cleanConfiguration(): bool
{
    $keys = ['MYMODULE_KEY1', 'MYMODULE_KEY2', 'MYMODULE_KEY3'];
    foreach ($keys as $key) {
        Configuration::deleteByName($key);
    }
    return true;
}

#Convencion de nombres

ElementoConvencionEjemplo
Nombre del modulolowercase, sin guiones, < 32 charsmymodule, ecompayments
Clases PHPPascalCaseMyModule, MyModuleItem
Metodos PHPcamelCasegetOrderTotal, processPayment
Claves ConfigurationMAYUSCULAS_CON_NOMBRE_MODULOMYMODULE_API_KEY
Tablas DBprefijo_modulo_entidadps_mymodule_orders
Hooks registradoscamelCase del nombre del hookhookDisplayHeader
Archivos de modulosnake_case o kebab-casemy_module_item.php
IDs de CSS/JSkebab-case con prefijo modulomymodule-main-style

#Checklist antes de publicar

ItemVerificacion
Seguridadif (!defined('_PS_VERSION_')) en todos los PHP
SQLpSQL() en todas las entradas, (int) en IDs
XSShtmlspecialchars() o escape:'html' en templates
Instalacioninstall() devuelve false correctamente en errores
Desinstalacionuninstall() limpia TODOS los datos del modulo
UpgradeScripts en upgrade/ para cada cambio de schema
TraduccionesTodas las strings en trans() o l()
CompatibilidadProbado en PS 8.x y PHP 8.1+
RendimientoQueries con indices, sin N+1
index.phpArchivo de seguridad en todos los subdirectorios
Descargar en Markdown Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.