---
title: Buenas practicas para modulos PrestaShop
section: modules
slug: best-practices
description: "Guia de buenas practicas para el desarrollo de modulos PrestaShop: seguridad, rendimiento, compatibilidad, naming conventions, instalacion/desinstalacion y testing."
keywords: prestashop buenas practicas modulo seguridad rendimiento compatibilidad naming instalacion desinstalacion
last_updated: 2024-12-01
source_url: "https://ayudaprestashop.es/modules/best-practices"
---

# Buenas practicas para modulos PrestaShop

> Guia de buenas practicas para el desarrollo de modulos PrestaShop: seguridad, rendimiento, compatibilidad, naming conventions, instalacion/desinstalacion y testing.

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

| Practica | Impacto | Como implementar |
| --- | --- | --- |
| Cachear queries pesadas | Alto | Cache::getInstance()->remember() |
| Usar indices en columnas de busqueda | Alto | ADD INDEX en install() |
| Evitar N+1 queries en hooks | Alto | Una sola query con JOIN |
| Cargar CSS/JS solo cuando se necesitan | Medio | Verificar $controller->php_self |
| Usar LazyLoad en imagenes del modulo | Medio | loading='lazy' en <img> |
| No hacer peticiones HTTP en hooks sync | Alto | Usar 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

| Elemento | Convencion | Ejemplo |
| --- | --- | --- |
| Nombre del modulo | lowercase, sin guiones, < 32 chars | mymodule, ecompayments |
| Clases PHP | PascalCase | MyModule, MyModuleItem |
| Metodos PHP | camelCase | getOrderTotal, processPayment |
| Claves Configuration | MAYUSCULAS_CON_NOMBRE_MODULO | MYMODULE_API_KEY |
| Tablas DB | prefijo_modulo_entidad | ps_mymodule_orders |
| Hooks registrados | camelCase del nombre del hook | hookDisplayHeader |
| Archivos de modulo | snake_case o kebab-case | my_module_item.php |
| IDs de CSS/JS | kebab-case con prefijo modulo | mymodule-main-style |

## Checklist antes de publicar

| Item | Verificacion |
| --- | --- |
| Seguridad | if (!defined('_PS_VERSION_')) en todos los PHP |
| SQL | pSQL() en todas las entradas, (int) en IDs |
| XSS | htmlspecialchars() o escape:'html' en templates |
| Instalacion | install() devuelve false correctamente en errores |
| Desinstalacion | uninstall() limpia TODOS los datos del modulo |
| Upgrade | Scripts en upgrade/ para cada cambio de schema |
| Traducciones | Todas las strings en trans() o l() |
| Compatibilidad | Probado en PS 8.x y PHP 8.1+ |
| Rendimiento | Queries con indices, sin N+1 |
| index.php | Archivo de seguridad en todos los subdirectorios |


---

*Fuente: [https://ayudaprestashop.es/modules/best-practices](https://ayudaprestashop.es/modules/best-practices). Version Markdown generada automaticamente para consumo por LLMs.*
