---
title: Grid System moderno — PS 1.7+
section: trucos
slug: admin-grid
description: "Guia completa del Grid System moderno de PrestaShop: GridDefinitionFactory, QueryBuilder, columnas, filtros, acciones de fila y añadir columnas a grids existentes."
keywords: prestashop grid system gridDefinition queryBuilder columnas filtros admin moderno symfony
last_updated: 2024-12-01
source_url: "https://ayudaprestashop.es/trucos/admin-grid"
---

# Grid System moderno — PS 1.7+

> Guia completa del Grid System moderno de PrestaShop: GridDefinitionFactory, QueryBuilder, columnas, filtros, acciones de fila y añadir columnas a grids existentes.

El **Grid System** de PrestaShop es el sistema moderno para crear listas en el BackOffice. Reemplaza a `HelperList` con una arquitectura Symfony basada en servicios, con filtros, ordenacion, paginacion y acciones integradas.

## Arquitectura del Grid System

*Estructura de archivos para un Grid*

```bash
src/
├── Grid/
│   ├── Definition/
│   │   └── Factory/
│   │       └── MyEntityGridDefinitionFactory.php  # Columnas, filtros, acciones
│   └── Query/
│       └── MyEntityGridQueryBuilder.php          # Query SQL/DBAL
```

## Grid Definition Factory

*src/Grid/Definition/Factory/MyEntityGridDefinitionFactory.php*

```php
<?php

declare(strict_types=1);

namespace MyModule\Grid\Definition\Factory;

use PrestaShop\PrestaShop\Core\Grid\Action\Row\RowActionCollection;
use PrestaShop\PrestaShop\Core\Grid\Action\Row\Type\LinkRowAction;
use PrestaShop\PrestaShop\Core\Grid\Column\ColumnCollection;
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ActionColumn;
use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn;
use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\AbstractGridDefinitionFactory;
use PrestaShop\PrestaShop\Core\Grid\Filter\Filter;
use PrestaShop\PrestaShop\Core\Grid\Filter\FilterCollection;
use Symfony\Component\Form\Extension\Core\Type\TextType;

final class MyEntityGridDefinitionFactory extends AbstractGridDefinitionFactory
{
    protected function getId(): string
    {
        return 'my_entity';
    }

    protected function getName(): string
    {
        return $this->trans('My Entities', [], 'Modules.Mymodule.Admin');
    }

    protected function getColumns(): ColumnCollection
    {
        return (new ColumnCollection())
            ->add(
                (new DataColumn('id_my_entity'))
                    ->setName($this->trans('ID', [], 'Admin.Global'))
                    ->setOptions(['field' => 'id_my_entity'])
            )
            ->add(
                (new DataColumn('name'))
                    ->setName($this->trans('Name', [], 'Admin.Global'))
                    ->setOptions(['field' => 'name'])
            )
            ->add(
                (new DataColumn('active'))
                    ->setName($this->trans('Enabled', [], 'Admin.Global'))
                    ->setOptions(['field' => 'active'])
            )
            ->add(
                (new ActionColumn('actions'))
                    ->setName($this->trans('Actions', [], 'Admin.Global'))
                    ->setOptions(['actions' => $this->getRowActions()])
            );
    }

    protected function getFilters(): FilterCollection
    {
        return (new FilterCollection())
            ->add(
                (new Filter('id_my_entity', TextType::class))
                    ->setTypeOptions(['required' => false, 'attr' => ['placeholder' => 'ID']])
                    ->setAssociatedColumn('id_my_entity')
            )
            ->add(
                (new Filter('name', TextType::class))
                    ->setTypeOptions(['required' => false])
                    ->setAssociatedColumn('name')
            );
    }

    private function getRowActions(): RowActionCollection
    {
        return (new RowActionCollection())
            ->add(
                (new LinkRowAction('edit'))
                    ->setName($this->trans('Edit', [], 'Admin.Actions'))
                    ->setIcon('edit')
                    ->setOptions([
                        'route'             => 'admin_mymodule_myentity_edit',
                        'route_param_name'  => 'id',
                        'route_param_field' => 'id_my_entity',
                    ])
            );
    }
}
```

## Grid Query Builder

*src/Grid/Query/MyEntityGridQueryBuilder.php*

```php
<?php

declare(strict_types=1);

namespace MyModule\Grid\Query;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Query\QueryBuilder;
use PrestaShop\PrestaShop\Core\Grid\Query\AbstractDoctrineQueryBuilder;
use PrestaShop\PrestaShop\Core\Grid\Search\SearchCriteriaInterface;

final class MyEntityGridQueryBuilder extends AbstractDoctrineQueryBuilder
{
    private string $dbPrefix;

    public function __construct(Connection $connection, string $dbPrefix)
    {
        parent::__construct($connection);
        $this->dbPrefix = $dbPrefix;
    }

    public function getSearchQueryBuilder(SearchCriteriaInterface $searchCriteria): QueryBuilder
    {
        $qb = $this->getBaseQuery();
        $qb->select('m.id_my_entity, m.name, m.active');

        $this->applyFilters($qb, $searchCriteria);
        $this->applySorting($qb, $searchCriteria);
        $this->applyPagination($qb, $searchCriteria);

        return $qb;
    }

    public function getCountQueryBuilder(SearchCriteriaInterface $searchCriteria): QueryBuilder
    {
        $qb = $this->getBaseQuery();
        $qb->select('COUNT(m.id_my_entity) AS total');
        $this->applyFilters($qb, $searchCriteria);
        return $qb;
    }

    private function getBaseQuery(): QueryBuilder
    {
        return $this->connection->createQueryBuilder()
            ->from($this->dbPrefix . 'my_entity', 'm');
    }

    private function applyFilters(QueryBuilder $qb, SearchCriteriaInterface $criteria): void
    {
        foreach ($criteria->getFilters() as $field => $value) {
            if ('id_my_entity' === $field) {
                $qb->andWhere('m.id_my_entity = :id')->setParameter('id', (int)$value);
            } elseif ('name' === $field) {
                $qb->andWhere('m.name LIKE :name')->setParameter('name', '%' . $value . '%');
            }
        }
    }

    private function applySorting(QueryBuilder $qb, SearchCriteriaInterface $criteria): void
    {
        if ($criteria->getOrderBy()) {
            $qb->orderBy('m.' . $criteria->getOrderBy(), $criteria->getOrderWay() ?? 'ASC');
        }
    }

    private function applyPagination(QueryBuilder $qb, SearchCriteriaInterface $criteria): void
    {
        if (null !== $criteria->getOffset()) {
            $qb->setFirstResult($criteria->getOffset());
        }
        if (null !== $criteria->getLimit()) {
            $qb->setMaxResults($criteria->getLimit());
        }
    }
}
```

## Extender grids existentes

Para añadir columnas o filtros a grids del core (Pedidos, Productos, Clientes...), usa el hook `action{GridName}GridDefinitionModifier`.

*Añadir columna al grid de Pedidos*

```php
<?php

// Nombre del hook: action + GridId (camelCase) + GridDefinitionModifier
// Grid ID 'order' → hookActionOrderGridDefinitionModifier
// Grid ID 'product' → hookActionProductGridDefinitionModifier
// Grid ID 'customer' → hookActionCustomerGridDefinitionModifier

public function hookActionOrderGridDefinitionModifier(array $params): void
{
    /** @var \PrestaShop\PrestaShop\Core\Grid\Definition\GridDefinitionInterface $definition */
    $definition = $params['definition'];

    // Añadir columna
    $definition->getColumns()->addAfter(
        'reference',   // Despues de la columna 'reference'
        (new DataColumn('my_data'))
            ->setName($this->trans('Mi dato', [], 'Modules.Mymodule.Admin'))
            ->setOptions(['field' => 'my_data'])
    );

    // Añadir filtro
    $definition->getFilters()->add(
        (new Filter('my_data', TextType::class))
            ->setAssociatedColumn('my_data')
    );
}

// Complementar con el query modifier para que el campo este en la query:
public function hookActionOrderGridQueryBuilderModifier(array $params): void
{
    /** @var QueryBuilder $qb */
    $qb = $params['search_query_builder'];
    $qb->addSelect('oe.my_data');
    $qb->leftJoin('o', _DB_PREFIX_ . 'my_order_extra', 'oe', 'oe.id_order = o.id_order');
}
```


---

*Fuente: [https://ayudaprestashop.es/trucos/admin-grid](https://ayudaprestashop.es/trucos/admin-grid). Version Markdown generada automaticamente para consumo por LLMs.*
