📊 Grid System — columnas y acciones custom en listados BO
Actualizado: 2025-01-15
#El Grid System de PS 1.7+
El Grid System moderno de PS usa hooks action{GridId}GridDefinitionModifier para que los modulos puedan anadir columnas, filtros y acciones a cualquier listado del BO sin overrides. Cada grid tiene un ID unico (ej: order, product, customer).
#Anadir columna a grid existente
Anadir columna 'Margen' al listado de pedidos
php
<?php
use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn;
use PrestaShop\PrestaShop\Core\Grid\Filter\Filter;
use Symfony\Component\Form\Extension\Core\Type\TextType;
public function install()
{
return parent::install()
&& $this->registerHook('actionOrderGridDefinitionModifier')
&& $this->registerHook('actionOrderGridQueryBuilderModifier');
}
/**
* Modificar la DEFINICION del grid (columnas, filtros, acciones)
*/
public function hookActionOrderGridDefinitionModifier(array $params): void
{
/** @var \PrestaShop\PrestaShop\Core\Grid\Definition\GridDefinitionInterface $definition */
$definition = $params['definition'];
// Anadir columna de margen de beneficio
$definition
->getColumns()
->addAfter(
'total_paid_tax_incl', // Despues de esta columna existente
(new DataColumn('profit_margin'))
->setName('Margen')
->setOptions([
'field' => 'profit_margin',
])
);
// Anadir filtro para la nueva columna
$definition
->getFilters()
->add(
(new Filter('profit_margin', TextType::class))
->setTypeOptions([
'required' => false,
'attr' => ['placeholder' => 'Margen...'],
])
->setAssociatedColumn('profit_margin')
);
}
/**
* Modificar el QUERY del grid (JOINs, campos)
*/
public function hookActionOrderGridQueryBuilderModifier(array $params): void
{
/** @var \Doctrine\DBAL\Query\QueryBuilder $searchQueryBuilder */
$searchQueryBuilder = $params['search_query_builder'];
/** @var \PrestaShop\PrestaShop\Core\Search\Filters\OrderFilters $searchCriteria */
$searchCriteria = $params['search_criteria'];
// Anadir subquery para calcular margen
$searchQueryBuilder->addSelect(
'ROUND(o.total_paid_tax_excl - IFNULL(margin.cost, 0), 2) AS profit_margin'
);
// JOIN con subconsulta de coste
$searchQueryBuilder->leftJoin(
'o',
'(' .
'SELECT od.id_order, SUM(od.product_quantity * od.original_wholesale_price) as cost ' .
'FROM `' . _DB_PREFIX_ . 'order_detail` od ' .
'GROUP BY od.id_order' .
')',
'margin',
'o.id_order = margin.id_order'
);
// Aplicar filtro si el usuario lo uso
foreach ($searchCriteria->getFilters() as $filterName => $filterValue) {
if ($filterName === 'profit_margin' && !empty($filterValue)) {
$searchQueryBuilder->andHaving(
'profit_margin >= :margin_filter'
);
$searchQueryBuilder->setParameter('margin_filter', (float) $filterValue);
}
}
}
#Anadir accion por fila
Boton 'Imprimir etiqueta' en cada fila del listado de pedidos
php
<?php
use PrestaShop\PrestaShop\Core\Grid\Action\Row\Type\LinkRowAction;
public function hookActionOrderGridDefinitionModifier(array $params): void
{
$definition = $params['definition'];
// Anadir accion de fila
$definition
->getGridActions() // Acciones globales (arriba del grid)
// O para acciones por fila:
;
$definition
->getColumns()
->addAfter('actions', // El grupo de acciones existente
// ... o modificar el actions column existente
);
// Anadir boton en la columna de acciones
$definition->getRowActions()->add(
(new LinkRowAction('print_label'))
->setName('Imprimir etiqueta')
->setIcon('print')
->setOptions([
'route' => 'ecom_shipping_print_label',
'route_param_name'=> 'orderId',
'route_param_field' => 'id_order',
])
);
}
#Anadir bulk action
Accion masiva: 'Exportar seleccionados a CSV'
php
<?php
use PrestaShop\PrestaShop\Core\Grid\Action\Bulk\Type\SubmitBulkAction;
public function hookActionOrderGridDefinitionModifier(array $params): void
{
$definition = $params['definition'];
$definition->getBulkActions()->add(
(new SubmitBulkAction('export_csv'))
->setName('Exportar a CSV')
->setOptions([
'submit_route' => 'ecom_export_orders_csv',
])
);
}
#Modificar filtros
Anadir filtro dropdown al listado de productos
php
<?php
use PrestaShop\PrestaShop\Core\Grid\Filter\Filter;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
public function hookActionProductGridDefinitionModifier(array $params): void
{
$definition = $params['definition'];
// Filtro: margen de beneficio (rangos)
$definition->getFilters()->add(
(new Filter('margin_range', ChoiceType::class))
->setTypeOptions([
'choices' => [
'Todos' => '',
'Negativo' => 'negative',
'0-10%' => 'low',
'10-30%' => 'medium',
'>30%' => 'high',
],
'required' => false,
'placeholder' => 'Margen...',
])
->setAssociatedColumn('profit_margin')
);
}
public function hookActionProductGridQueryBuilderModifier(array $params): void
{
$searchQueryBuilder = $params['search_query_builder'];
$searchCriteria = $params['search_criteria'];
foreach ($searchCriteria->getFilters() as $name => $value) {
if ($name === 'margin_range' && !empty($value)) {
switch ($value) {
case 'negative':
$searchQueryBuilder->andWhere('p.price < p.wholesale_price');
break;
case 'low':
$searchQueryBuilder->andWhere(
'((p.price - p.wholesale_price) / NULLIF(p.price, 0)) BETWEEN 0 AND 0.10'
);
break;
case 'medium':
$searchQueryBuilder->andWhere(
'((p.price - p.wholesale_price) / NULLIF(p.price, 0)) BETWEEN 0.10 AND 0.30'
);
break;
case 'high':
$searchQueryBuilder->andWhere(
'((p.price - p.wholesale_price) / NULLIF(p.price, 0)) > 0.30'
);
break;
}
}
}
}
#Hooks disponibles para grids
| Grid ID | Hook Definition | Hook Query | Listado |
|---|---|---|---|
| order | actionOrderGridDefinitionModifier | actionOrderGridQueryBuilderModifier | Pedidos |
| product | actionProductGridDefinitionModifier | actionProductGridQueryBuilderModifier | Productos |
| customer | actionCustomerGridDefinitionModifier | actionCustomerGridQueryBuilderModifier | Clientes |
| cart | actionCartGridDefinitionModifier | actionCartGridQueryBuilderModifier | Carritos |
| invoice | actionInvoiceGridDefinitionModifier | actionInvoiceGridQueryBuilderModifier | Facturas |
| module | actionModuleGridDefinitionModifier | actionModuleGridQueryBuilderModifier | Modulos |
| employee | actionEmployeeGridDefinitionModifier | actionEmployeeGridQueryBuilderModifier | Empleados |
Descubrir el Grid ID
Para descubrir el grid ID de un listado, busca en el controller Symfony del BO la linea $gridFactory->getGrid() o el servicio que contiene grid_definition_factory. El ID es el primer argumento del GridDefinition.
Descargar en Markdown
Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.