---
title: Estructura de un modulo PrestaShop
section: modules
slug: structure
description: Guia completa sobre la estructura de archivos y directorios de un modulo PrestaShop. Desde el archivo principal hasta los controladores, templates y assets.
keywords: prestashop modulo estructura directorios archivos php
last_updated: 2024-12-01
source_url: "https://ayudaprestashop.es/modules/structure"
---

# Estructura de un modulo PrestaShop

> Guia completa sobre la estructura de archivos y directorios de un modulo PrestaShop. Desde el archivo principal hasta los controladores, templates y assets.

Un modulo PrestaShop es un **plugin PHP autonomo** que extiende las funcionalidades de la tienda sin modificar el core. Toda la logica, templates, assets y configuracion del modulo viven dentro de un unico directorio bajo `/modules/nombre-del-modulo/`.

> **[TIP] Convencion de nombres**
>
> El nombre del directorio del modulo debe coincidir exactamente con el nombre de la clase principal y el valor de `$this->name`. Usa solo letras minusculas y guiones bajos (`mi_modulo`), sin guiones ni espacios.

## Estructura basica

*Estructura de directorios de un modulo completo*

```bash
mymodule/
├── mymodule.php                  # Archivo principal del modulo (requerido)
├── config.xml                    # Cache de configuracion (auto-generado)
├── logo.png                      # Logo del modulo (80x80px)
│
├── config/                       # Configuracion Symfony (PS 1.7+)
│   ├── routes.yml                # Definicion de rutas
│   └── services.yml              # Registro de servicios DI
│
├── controllers/
│   ├── admin/
│   │   └── AdminMyModuleController.php
│   └── front/
│       ├── main.php              # ModuleFrontController principal
│       └── ajax.php              # Controlador AJAX
│
├── src/                          # Clases PHP (PSR-4 autoloading)
│   ├── Entity/
│   │   └── MyEntity.php          # Entidad Doctrine (PS 1.7+)
│   ├── Repository/
│   │   └── MyEntityRepository.php
│   └── Service/
│       └── MyService.php
│
├── views/
│   ├── templates/
│   │   ├── hook/                 # Templates de hooks
│   │   │   ├── displayHome.tpl
│   │   │   └── displayProductButtons.tpl
│   │   ├── admin/                # Templates del admin
│   │   │   └── configure.tpl
│   │   └── front/                # Templates del front office
│   │       └── mypage.tpl
│   ├── js/
│   │   ├── front.js
│   │   └── admin.js
│   └── css/
│       ├── front.css
│       └── admin.css
│
├── translations/                 # Archivos de traduccion .xlf
│   ├── es.xlf
│   ├── en.xlf
│   └── fr.xlf
│
├── upgrade/                      # Scripts de actualizacion
│   ├── install-1.0.1.php
│   └── install-1.0.2.php
│
├── override/                     # Overrides especificos del modulo
│   └── classes/
│       └── Product.php
│
└── vendor/                       # Dependencias (Composer)
    └── autoload.php
```

## Archivo principal

El archivo `mymodule.php` es el **corazon del modulo**. Debe contener una clase con el mismo nombre del directorio que extiende `Module` (o una de sus subclases como `PaymentModule`, `CarrierModule`, etc.).

*mymodule/mymodule.php*

```php
<?php

if (!defined('_PS_VERSION_')) {
    exit;
}

class MyModule extends Module
{
    public function __construct()
    {
        $this->name          = 'mymodule';          // Mismo que el directorio
        $this->tab           = 'front_office_features'; // Categoria en el marketplace
        $this->version       = '1.0.0';
        $this->author        = 'Tu Empresa';
        $this->need_instance = 0;                   // 0 = no instanciar en admin
        $this->bootstrap     = true;                // Usar Bootstrap en admin
        $this->ps_versions_compliancy = [
            'min' => '1.7.0',
            'max' => _PS_VERSION_,
        ];

        parent::__construct();  // Siempre despues de definir $this->name

        $this->displayName = $this->trans(
            'Mi Modulo',
            [],
            'Modules.Mymodule.Admin'
        );
        $this->description = $this->trans(
            'Descripcion de mi modulo para PrestaShop.',
            [],
            'Modules.Mymodule.Admin'
        );
    }

    /**
     * Instalacion del modulo
     */
    public function install(): bool
    {
        return parent::install()
            && $this->registerHook('displayHome')
            && $this->registerHook('actionValidateOrder')
            && $this->registerHook('actionFrontControllerSetMedia')
            && $this->installDatabase();
    }

    /**
     * Desinstalacion del modulo
     */
    public function uninstall(): bool
    {
        return parent::uninstall()
            && $this->uninstallDatabase();
    }

    /**
     * Pagina de configuracion en el admin
     */
    public function getContent(): string
    {
        $output = '';

        if (Tools::isSubmit('submit' . $this->name)) {
            $myValue = Tools::getValue('MY_CONFIG_VALUE');
            Configuration::updateValue('MY_CONFIG_VALUE', $myValue);
            $output .= $this->displayConfirmation(
                $this->trans('Configuracion guardada', [], 'Admin.Notifications.Success')
            );
        }

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

    private function renderConfigForm(): string
    {
        $helper = new HelperForm();
        // ... configuracion del HelperForm
        return $helper->generateForm([/* fields */]);
    }

    private function installDatabase(): bool
    {
        $sql = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'mymodule_data` (
            `id_mymodule` int(10) unsigned NOT NULL AUTO_INCREMENT,
            `id_order` int(10) unsigned NOT NULL,
            `data` text,
            `created_at` datetime NOT NULL,
            PRIMARY KEY (`id_mymodule`)
        ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4;';

        return Db::getInstance()->execute($sql);
    }

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

    // Hook handler
    public function hookDisplayHome(array $params): string
    {
        $this->context->smarty->assign([
            'greeting' => 'Hola desde mi modulo',
        ]);

        return $this->display(__FILE__, 'views/templates/hook/displayHome.tpl');
    }
}
```

## Templates y vistas

Los templates de hooks van en `views/templates/hook/`. El nombre del archivo debe coincidir con el nombre del hook que lo renderiza (sin el prefijo `hook`).

*views/templates/hook/displayHome.tpl*

```smarty
{**
 * Template para el hook displayHome
 *}
<div class="mymodule-home-block">
    <h2>{l s='Bienvenido' mod='mymodule'}</h2>
    <p>{$greeting|escape:'html':'UTF-8'}</p>
</div>
```

> **[!] Siempre escapa las variables Smarty**
>
> Usa siempre `|escape:'html':'UTF-8'` en variables de usuario para prevenir XSS. Las variables del sistema de PS ya estan escapadas.

## Scripts de upgrade

*upgrade/install-1.0.1.php*

```php
<?php

if (!defined('_PS_VERSION_')) {
    exit;
}

/**
 * Script de actualizacion a la version 1.0.1
 * Se ejecuta automaticamente al actualizar el modulo
 */
function upgrade_module_1_0_1($module)
{
    // Añadir nueva columna a la tabla
    $sql = 'ALTER TABLE `' . _DB_PREFIX_ . 'mymodule_data`
        ADD COLUMN `status` tinyint(1) NOT NULL DEFAULT 1 AFTER `data`';

    if (!Db::getInstance()->execute($sql)) {
        return false;
    }

    // Registrar nuevo hook
    return $module->registerHook('actionOrderHistoryAddAfter');
}
```


---

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