📝
Formularios Symfony en modulos PrestaShop 8/9
Actualizado: 2024-12-01
PrestaShop 8+ utiliza el componente Symfony Form para las paginas de configuracion del Back Office. El patron recomendado usa tres clases: el Form Type (estructura de campos), el DataConfiguration (mapeo a la tabla Configuration) y el FormHandler (orquesta carga, guardado y hooks).
#El patron triple: Type + DataConfiguration + DataProvider
| Clase | Responsabilidad | Ubicacion |
|---|---|---|
| MyCustomType | Define los campos del formulario | src/Form/MyCustomType.php |
| MyDataConfiguration | Mapea campos a claves de Configuration | src/Form/MyDataConfiguration.php |
| ConfigurableFormDataProvider | Carga y guarda datos del form | Clase del core — instanciar en services.yml |
| FormHandler | Orquesta form factory, hooks y data provider | Clase del core — instanciar en services.yml |
#Form Type
src/Form/MyCustomType.php
php
<?php
declare(strict_types=1);
namespace MyModule\Form;
use PrestaShopBundle\Form\Admin\Type\TranslatorAwareType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
final class MyCustomType extends TranslatorAwareType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('my_setting', TextType::class, [
'label' => $this->trans('Nombre del ajuste', 'Modules.Mymodule.Admin'),
'required' => false,
])
->add('my_flag', CheckboxType::class, [
'label' => $this->trans('Activar funcionalidad', 'Modules.Mymodule.Admin'),
'required' => false,
]);
}
}
#Data Configuration
src/Form/MyDataConfiguration.php — mapeo a ps_configuration
php
<?php
declare(strict_types=1);
namespace MyModule\Form;
use PrestaShop\PrestaShop\Core\Configuration\DataConfigurationInterface;
use PrestaShop\PrestaShop\Adapter\Configuration;
final class MyDataConfiguration implements DataConfigurationInterface
{
private Configuration $configuration;
public function __construct(Configuration $configuration)
{
$this->configuration = $configuration;
}
/**
* Devuelve los valores actuales para pre-rellenar el formulario.
*/
public function getConfiguration(): array
{
return [
'my_setting' => $this->configuration->get('MY_MODULE_SETTING', ''),
'my_flag' => (bool) $this->configuration->get('MY_MODULE_FLAG', false),
];
}
/**
* Guarda los valores enviados por el formulario.
* Devuelve array de errores (vacio = exito).
*/
public function updateConfiguration(array $config): array
{
$this->configuration->set('MY_MODULE_SETTING', $config['my_setting']);
$this->configuration->set('MY_MODULE_FLAG', (int) $config['my_flag']);
return []; // sin errores
}
/**
* Validacion previa (opcional — dejar en true si usas Form Validation).
*/
public function validateConfiguration(array $configuration): bool
{
return true;
}
}
#Registro en services.yml
config/services.yml — declaracion de todos los servicios del formulario
yaml
services:
_defaults:
autowire: true
autoconfigure: true
public: true
# 1. Form Type
my_module.form.type:
class: MyModule\Form\MyCustomType
parent: 'form.type.translatable.aware'
tags:
- { name: form.type }
# 2. Data Configuration (mapea campos <-> Configuration)
my_module.form.data_configuration:
class: MyModule\Form\MyDataConfiguration
arguments: ['@prestashop.adapter.legacy.configuration']
# 3. Data Provider (usa la clase del core)
my_module.form.data_provider:
class: PrestaShop\PrestaShop\Core\Form\ConfigurableFormDataProvider
arguments:
- '@my_module.form.data_configuration'
- '@prestashop.core.localization.locale.context'
# 4. Form Handler (orquesta todo)
my_module.form.handler:
class: PrestaShop\PrestaShop\Core\Form\FormHandler
arguments:
- '@form.factory'
- '@prestashop.core.hook.dispatcher'
- '@my_module.form.data_provider'
- 'MyModule\Form\MyCustomType'
- 'MyModuleForm' # sufijo para los hooks: actionMyModuleFormSave, etc.
#Renderizar en el Controller
src/Controller/Admin/ConfigurationController.php
php
<?php
declare(strict_types=1);
namespace MyModule\Controller\Admin;
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class ConfigurationController extends FrameworkBundleAdminController
{
public function indexAction(Request $request): Response
{
$formHandler = $this->get('my_module.form.handler');
$form = $formHandler->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$errors = $formHandler->save($form->getData());
if (empty($errors)) {
$this->addFlash(
'success',
$this->trans('Configuracion guardada correctamente.', 'Admin.Notifications.Success')
);
} else {
foreach ($errors as $error) {
$this->addFlash('error', $error);
}
}
}
return $this->render(
'@Modules/my_module/views/templates/admin/configure.html.twig',
['form' => $form->createView()]
);
}
}
#Tipos especiales de PrestaShop
Tipos de campo disponibles en PrestaShopBundle
php
<?php
// Switch on/off (toggle)
use PrestaShopBundle\Form\Admin\Type\SwitchType;
// Campo de texto multilingual
use PrestaShopBundle\Form\Admin\Type\TranslatableType;
// Selector de categorias
use PrestaShopBundle\Form\Admin\Type\CategoryChoiceTreeType;
// Selector de impuestos
use PrestaShopBundle\Form\Admin\Type\TaxChoiceType;
// Selector de moneda
use PrestaShopBundle\Form\Admin\Type\CurrencyChoiceType;
// Textarea con TinyMCE (editor rico)
use PrestaShopBundle\Form\Admin\Type\FormattedTextareaType;
// Ejemplo con SwitchType
$builder->add('active', SwitchType::class, [
'label' => $this->trans('Activo', 'Admin.Global'),
'required' => false,
]);
// Ejemplo con TranslatableType (campo multilingual)
$builder->add('description', TranslatableType::class, [
'label' => $this->trans('Descripcion', 'Admin.Global'),
'type' => FormattedTextareaType::class,
'options' => ['required' => false],
]);
CSRF incluido automaticamente
Al usar FormHandler del core, la proteccion CSRF de Symfony se aplica automaticamente. No es necesario añadir nada extra.
Descargar en Markdown
Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.