Sin impuesto Con impuesto

Añadir un campo a los proveedores en PrestaShop 8 con hooks

Un compañero añadía un campo a los proveedores y no le salía en el formulario: en PrestaShop 8 esa pantalla es de Symfony. Gustavo le indicó los hooks FormBuilderModifier y AfterUpdate/AfterCreate FormHandler. Te dejamos un ejemplo ordenado que guarda el dato en una tabla propia.

Equipo Rekire
Actualizado: 11/10/2024 9
Añadir un campo a los proveedores en PrestaShop 8 con hooks
Compartir:

Un compañero estaba programando un módulo para añadir dos campos a los proveedores, entre ellos la provincia. La columna se creaba bien en la base de datos, pero al editar un proveedor el campo no aparecía en el formulario, y un var_dump en su hook no se ejecutaba nunca. La respuesta de Gustavo: en PrestaShop 8 esa pantalla es de Symfony y hay que usar los hooks de los formularios, no los antiguos.

Por qué no salía el campo

Desde la 1.7, PrestaShop ha ido pasando las pantallas del back-office a Symfony. En las migradas, como la de proveedores, el formulario se construye con un form builder y los hooks de las páginas antiguas ya no se llaman. Para tocarlo, PrestaShop lanza tres hooks cuyo nombre sigue siempre el mismo patrón:

  • action<Entidad>FormBuilderModifier: para añadir campos al formulario y darles valor.
  • actionAfterCreate<Entidad>FormHandler: después de crear el registro.
  • actionAfterUpdate<Entidad>FormHandler: después de guardarlo al editar.

Para proveedores, la entidad es Supplier. Gustavo los usa con las categorías (actionAfterCreateCategoryFormHandler y compañía) y el compañero los adaptó a proveedores. Cuando le funcionó, compartió su código en el grupo; lo que sigue es una versión ordenada de esa idea.

1. Registrar los hooks y crear una tabla propia

El compañero añadió la columna directamente a la tabla de proveedores. Funciona, pero te expones a conflictos con actualizaciones de PrestaShop. Es más limpio guardar el dato en una tabla del módulo:

public function install()
{
    return parent::install()
        && $this->registerHook('actionSupplierFormBuilderModifier')
        && $this->registerHook('actionAfterCreateSupplierFormHandler')
        && $this->registerHook('actionAfterUpdateSupplierFormHandler')
        && Db::getInstance()->execute(
            'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'mimodulo_supplier` (
                `id_supplier` INT UNSIGNED NOT NULL PRIMARY KEY,
                `provincia` VARCHAR(64) NULL
            ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4'
        );
}

2. Añadir el campo al formulario

El hook recibe el form_builder, los datos con los que se rellena el formulario y el id del proveedor (vacío si es nuevo). Añades el campo, le das el valor guardado y vuelves a pasar los datos al formulario:

// Al principio del fichero del módulo, fuera de la clase:
use Symfony\Component\Form\Extension\Core\Type\TextType;

public function hookActionSupplierFormBuilderModifier(array $params)
{
    $formBuilder = $params['form_builder'];
    $formBuilder->add('provincia', TextType::class, [
        'label' => $this->l('Provincia'),
        'required' => false,
    ]);

    $idSupplier = isset($params['id']) ? (int) $params['id'] : 0;
    $params['data']['provincia'] = $idSupplier ? $this->getProvincia($idSupplier) : '';
    $formBuilder->setData($params['data']);
}

3. Guardar el valor

Los hooks de después de crear y de actualizar reciben el id del proveedor y lo que se envió en el formulario. Con los dos llamas a la misma función:

public function hookActionAfterCreateSupplierFormHandler(array $params)
{
    $this->guardarProvincia($params);
}

public function hookActionAfterUpdateSupplierFormHandler(array $params)
{
    $this->guardarProvincia($params);
}

private function guardarProvincia(array $params)
{
    $provincia = isset($params['form_data']['provincia']) ? (string) $params['form_data']['provincia'] : '';
    Db::getInstance()->insert('mimodulo_supplier', [
        'id_supplier' => (int) $params['id'],
        'provincia' => pSQL($provincia),
    ], false, true, Db::REPLACE);
}

private function getProvincia($idSupplier)
{
    return (string) Db::getInstance()->getValue(
        'SELECT `provincia` FROM `' . _DB_PREFIX_ . 'mimodulo_supplier` WHERE `id_supplier` = ' . (int) $idSupplier
    );
}

Con Db::REPLACE la misma llamada sirve para el primer guardado y para los siguientes, porque id_supplier es la clave de la tabla. Pruébalo antes en una copia de la tienda.

Detalles que conviene saber

  • Vacía la caché después de instalar. Si el hook no queda registrado, el campo no aparece y no verás ningún error.
  • Para mostrar el dato en la tienda, léelo de tu tabla en el hook o la plantilla donde lo necesites.
  • Si el campo tiene que estar en varios idiomas, ya no vale un TextType: PrestaShop tiene su propio tipo de campo traducible. Gustavo lo resumía meses después, cuando le tocó hacerlo en la ficha de producto: «hay que aprender Symfony sí o sí».
  • Al desinstalar el módulo, borra su tabla para no dejar restos.

Si el campo sigue sin salir

Antes de reescribir nada, comprueba tres cosas:

  1. En Diseño → Posiciones, que tu módulo aparece enganchado a actionSupplierFormBuilderModifier. Si lo instalaste antes de añadir el hook, reinstálalo o regístralo a mano.
  2. Que el hook se ejecuta. En las pantallas de Symfony un var_dump no siempre se ve; deja un registro temporal con PrestaShopLogger::addLog() y míralo en el registro del back-office.
  3. Con el modo depuración activo, revisa var/logs: un error dentro del hook puede hacer que el formulario se pinte sin tu campo.

El mismo patrón sirve para clientes, categorías, marcas y el resto de pantallas migradas: cambia Supplier por la entidad que toque.

Esto salió en @PrestashopEsp, la mayor comunidad PrestaShop de España en Telegram. Ver la conversación

Cargando...
Cookies
Volver arriba