---
title: Formularios Symfony — 6 modulos de ejemplo
section: sample-modules
slug: symfony-forms
description: 6 modulos de ejemplo para formularios Symfony en PrestaShop. Hooks de FormBuilder, upload image, CQRS, FormTypes reutilizables, configuracion y DataProviders.
last_updated: 2026-04
source_url: "https://ayudaprestashop.es/sample-modules/symfony-forms"
---

# Formularios Symfony — 6 modulos de ejemplo

> 6 modulos de ejemplo para formularios Symfony en PrestaShop. Hooks de FormBuilder, upload image, CQRS, FormTypes reutilizables, configuracion y DataProviders.

> **[I] 6 modulos, un patron**
>
> PrestaShop ofrece 6 modulos de ejemplo para formularios Symfony, cada uno mostrando un aspecto diferente: hooks, upload, CQRS, FormTypes reutilizables, configuracion simple y DataProviders.

## demoextendsymfonyform1 — Identifiable Object hooks

Ensena como usar hooks de **identifiable object** y **grid** para anadir campos a formularios existentes del BO (ej: formulario de proveedor, fabricante, etc.).

*Hooks para extender formularios de objetos existentes*

```php
<?php
// Anadir campo al formulario de Supplier
public function hookActionSupplierFormBuilderModifier(array $params): void
{
    /** @var FormBuilderInterface $formBuilder */
    $formBuilder = $params['form_builder'];
    $supplierId = $params['id'];

    // Anadir campo custom al formulario
    $formBuilder->add('demo_custom_field', TextType::class, [
        'label'    => 'My custom field',
        'required' => false,
        'data'     => $this->getCustomFieldValue($supplierId),
    ]);
}

// Guardar el valor cuando se envie el formulario
public function hookActionAfterUpdateSupplierFormHandler(array $params): void
{
    $supplierId = $params['id'];
    $formData   = $params['form_data'];

    $this->saveCustomFieldValue(
        $supplierId,
        $formData['demo_custom_field'] ?? ''
    );
}

// Tambien capturar la creacion
public function hookActionAfterCreateSupplierFormHandler(array $params): void
{
    $this->hookActionAfterUpdateSupplierFormHandler($params);
}
```

## demoextendsymfonyform2 — Upload image + Doctrine

Demuestra como insertar un campo **upload de imagen** en el formulario Symfony de 'Editar Proveedor' y como usar **Doctrine ORM** para gestionar el estado en BD de un objeto custom.

*Campo upload image en formulario Symfony*

```php
<?php
use PrestaShop\PrestaShop\Core\Form\IdentifiableObject\Builder\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints\Image;

public function hookActionSupplierFormBuilderModifier(array $params): void
{
    $formBuilder = $params['form_builder'];

    $formBuilder->add('demo_supplier_logo', FileType::class, [
        'label'       => 'Custom logo',
        'required'    => false,
        'constraints' => [
            new Image([
                'maxSize'   => '2M',
                'mimeTypes' => ['image/jpeg', 'image/png', 'image/webp'],
            ]),
        ],
        'attr' => [
            'accept' => 'image/jpeg,image/png,image/webp',
        ],
    ]);
}

// Guardar la imagen subida
public function hookActionAfterUpdateSupplierFormHandler(array $params): void
{
    $formData = $params['form_data'];
    $file = $formData['demo_supplier_logo'] ?? null;

    if ($file instanceof UploadedFile) {
        $filename = uniqid('supplier_') . '.' . $file->guessExtension();
        $file->move(_PS_IMG_DIR_ . 'demo/', $filename);

        // Guardar referencia en Doctrine entity
        $this->entityManager->persist(new SupplierLogo(
            $params['id'],
            $filename
        ));
        $this->entityManager->flush();
    }
}
```

## demoextendsymfonyform3 — Patron CQRS

Demuestra el patron **CQRS (Command Query Responsibility Segregation)** con hooks. Usa Commands para escritura y Queries para lectura, el patron recomendado en PS 9.x.

*CQRS — Command para escritura*

```php
<?php
// Command: accion de escritura
namespace PrestaShop\Module\DemoExtendSymfonyForm3\CQRS\Command;

class UpdateSupplierExtraDataCommand
{
    private int $supplierId;
    private string $extraField;

    public function __construct(int $supplierId, string $extraField)
    {
        $this->supplierId = $supplierId;
        $this->extraField = $extraField;
    }

    public function getSupplierId(): int { return $this->supplierId; }
    public function getExtraField(): string { return $this->extraField; }
}

// Handler: ejecuta el command
class UpdateSupplierExtraDataHandler
{
    public function __construct(
        private readonly Connection $connection,
        private readonly string $dbPrefix
    ) {}

    public function handle(UpdateSupplierExtraDataCommand $command): void
    {
        $this->connection->executeStatement(
            'INSERT INTO ' . $this->dbPrefix . 'demo_supplier_extra
             (id_supplier, extra_field) VALUES (:id, :val)
             ON DUPLICATE KEY UPDATE extra_field = :val',
            [
                'id'  => $command->getSupplierId(),
                'val' => $command->getExtraField(),
            ]
        );
    }
}

// En el hook del formulario:
public function hookActionAfterUpdateSupplierFormHandler(array $params): void
{
    $this->commandBus->handle(new UpdateSupplierExtraDataCommand(
        $params['id'],
        $params['form_data']['extra_field'] ?? ''
    ));
}
```

## demosymfonyform — FormTypes de PS en pagina nueva

Demuestra como crear una **pagina nueva en el BO** usando FormTypes que ya existen en PrestaShop (CountryChoiceType, CurrencyChoiceType, etc.).

*Reutilizar FormTypes existentes de PrestaShop*

```php
<?php
use PrestaShop\PrestaShop\Core\Form\FormChoiceProviderInterface;
use PrestaShopBundle\Form\Admin\Type\CountryChoiceType;
use PrestaShopBundle\Form\Admin\Type\Material\MaterialChoiceTableType;

class DemoConfigurationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            // Selector de pais con todos los paises de PS
            ->add('country', CountryChoiceType::class, [
                'label' => 'Select country',
            ])
            // Selector de moneda
            ->add('currency', CurrencyChoiceType::class, [
                'label' => 'Select currency',
            ])
            // Switch on/off (estilo Material Design)
            ->add('enable_feature', SwitchType::class, [
                'label' => 'Enable feature',
            ])
            // Tabla de seleccion multiple (estilo PS)
            ->add('categories', MaterialChoiceTableType::class, [
                'label'   => 'Categories',
                'choices' => $this->categoryChoices,
            ]);
    }
}
```

## demosymfonyformsimple — Config page simple

El ejemplo mas sencillo: crear una **pagina de configuracion** para tu modulo usando Symfony FormTypes. Ideal como punto de partida.

*Pagina de configuracion basica con Symfony*

```php
<?php
// Controller del modulo
class DemoConfigurationController extends FrameworkBundleAdminController
{
    public function indexAction(Request $request): Response
    {
        $form = $this->createForm(DemoConfigurationType::class, [
            'config_text'  => Configuration::get('DEMO_CONFIG_TEXT'),
            'config_bool'  => (bool) Configuration::get('DEMO_CONFIG_BOOL'),
        ]);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();
            Configuration::updateValue('DEMO_CONFIG_TEXT', $data['config_text']);
            Configuration::updateValue('DEMO_CONFIG_BOOL', $data['config_bool']);

            $this->addFlash('success', 'Settings updated!');
            return $this->redirectToRoute('demo_configuration');
        }

        return $this->render('@Modules/demosymfonyformsimple/views/templates/admin/configuration.html.twig', [
            'form' => $form->createView(),
        ]);
    }
}

// FormType
class DemoConfigurationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('config_text', TextType::class, [
                'label' => 'Text setting',
            ])
            ->add('config_bool', SwitchType::class, [
                'label' => 'Enable feature',
            ]);
    }
}
```

## demoformdataproviders — FormDataProvider hooks

Ilustra los hooks `FormDataProviderData` y `FormDataProviderDefaultData` para inyectar datos en formularios existentes sin modificar el FormType. Compatible desde PS 8.0.

*Hooks de FormDataProvider*

```php
<?php
// Inyectar datos por defecto en formulario de creacion
public function hookActionManufacturerFormDataProviderDefaultData(array &$params): void
{
    // Datos por defecto al crear un nuevo fabricante
    $params['data']['my_custom_field'] = 'Valor por defecto';
}

// Inyectar datos al editar un objeto existente
public function hookActionManufacturerFormDataProviderData(array &$params): void
{
    $manufacturerId = $params['data']['id'] ?? null;
    if ($manufacturerId) {
        $params['data']['my_custom_field'] = $this->getStoredValue($manufacturerId);
    }
}
```

## demoproductform — Extender producto BO

Demuestra las multiples opciones de extender el formulario de producto en el BO. Requiere PS 9.0+ (nueva pagina de producto).

*Anadir tab y campos al formulario de producto*

```php
<?php
// Anadir un tab personalizado al formulario de producto
public function hookActionProductFormBuilderModifier(array $params): void
{
    $formBuilder = $params['form_builder'];
    $productId   = $params['id'];

    // Anadir tab completo con NavigationTabType
    $formBuilder->add('demo_tab', NavigationTabType::class, [
        'label' => 'Demo Custom Tab',
    ]);

    // Anadir campos dentro del tab
    $formBuilder->get('demo_tab')
        ->add('custom_text', TextType::class, [
            'label'    => 'Custom text field',
            'required' => false,
            'data'     => $this->getProductCustomText($productId),
        ])
        ->add('custom_toggle', SwitchType::class, [
            'label' => 'Enable custom feature',
            'data'  => $this->isFeatureEnabled($productId),
        ]);
}

public function hookActionAfterUpdateProductFormHandler(array $params): void
{
    $productId = $params['id'];
    $formData  = $params['form_data'];

    $this->saveProductCustomData(
        $productId,
        $formData['demo_tab']['custom_text'] ?? '',
        $formData['demo_tab']['custom_toggle'] ?? false
    );
}
```

> **[TIP] Cual usar segun tu necesidad**
>
> - **Campo en formulario existente**: demoextendsymfonyform1 (hooks FormBuilder)
> - **Upload de archivos**: demoextendsymfonyform2
> - **CQRS avanzado**: demoextendsymfonyform3
> - **Pagina nueva con FormTypes PS**: demosymfonyform
> - **Config page simple**: demosymfonyformsimple (punto de partida)
> - **Solo inyectar datos**: demoformdataproviders
> - **Tab en producto**: demoproductform


---

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