Installation
composer require sylius/grid-bundle
Ensure Sylius\Bundle\GridBundle\SyliusGridBundle is registered in config/bundles.php.
First Grid Definition
Use the make:grid command to scaffold a grid:
php bin/console make:grid product
This generates:
config/grids/product.yaml).Basic Usage in a Controller
use Sylius\Bundle\GridBundle\Grid\GridFactory;
class ProductController
{
public function __construct(private GridFactory $gridFactory) {}
public function index(): Response
{
$grid = $this->gridFactory->create('product');
$grid->load();
return $this->render('product/index.html.twig', [
'grid' => $grid,
]);
}
}
Render in Twig
{{ grid('product') }}
The bundle provides built-in Twig extensions for rendering grids.
Define Fields in product.yaml
sylius_grid:
grids:
product:
driver:
name: doctrine/orm
options:
class: App\Entity\Product
fields:
id:
type: twig
options:
template: '@SyliusGrid/Field/id.html.twig'
name:
type: twig
options:
template: '@SyliusGrid/Field/text.html.twig'
actions:
item:
edit:
type: edit
options:
route: sylius_admin_product_edit
Load and Display
$grid = $gridFactory->create('product');
$grid->load(); // Executes queries, applies filters/sorting
return $this->render('product/index.html.twig', ['grid' => $grid]);
Customize with Filters/Sorting
filters:
search:
type: string
options:
label: 'Search'
field: name
sorting:
name:
label: Name
default: true
config/grids/*.{yaml,php}.
// config/grids/product.php
return [
'driver' => [
'name' => 'doctrine/orm',
'options' => ['class' => App\Entity\Product::class],
],
'fields' => [
'name' => ['type' => 'twig', 'options' => ['template' => '@App/Grid/Field/name.html.twig']],
],
];
GridFactory to create grids programmatically:
$grid = $gridFactory->create('product', [
'fields' => ['price' => ['type' => 'price']],
]);
text, date, price, boolean, enum, etc.
fields:
status:
type: enum
options:
choices: ['draft', 'published', 'archived']
FieldTypeInterface:
class CustomFieldType implements FieldTypeInterface
{
public function render(FieldView $view, array $options): string
{
return sprintf('<span>%s</span>', $view->getData());
}
}
Register as a service with the sylius.grid.field_type tag.string, number, date, enum, entity, etc.
filters:
category:
type: entity
options:
field: category
choices: '@sylius.repository.category'
$grid->getSorting()->add('createdAt', 'desc');
edit, delete, view.
actions:
item:
edit:
type: edit
options:
route: app_admin_product_edit
routeParameters:
id: resource.id
ActionTypeInterface:
class CustomActionType implements ActionTypeInterface
{
public function render(ActionView $view, array $options): string
{
return $this->renderLink($view, $options);
}
}
vendor/sylius/grid-bundle/Resources/views/ to templates/SyliusGrid/.type: twig with custom templates:
fields:
name:
type: twig
options:
template: '@App/Grid/Field/product_name.html.twig'
doctrine/orm driver for Eloquent-like queries:
driver:
name: doctrine/orm
options:
class: App\Entity\Product
repository: '@sylius.repository.product'
driver:
name: doctrine/orm
options:
repository: '@app.custom_product_repository'
json driver for API responses:
driver:
name: json
options:
data: '@sylius.grid.data_collector.product'
SerializerInterface:
$grid->getDataCollector()->setSerializer(new JsonSerializer());
// src/EventListener/GridSubscriber.php
class GridSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
GridEvents::PRE_LOAD => 'onPreLoad',
];
}
public function onPreLoad(GridEvent $event): void
{
$grid = $event->getGrid();
$grid->getFilters()->add('custom', new CustomFilter());
}
}
GridTestTrait:
use Sylius\Bundle\GridBundle\Tests\Functional\GridTestTrait;
class ProductGridTest extends WebTestCase
{
use GridTestTrait;
public function testGridRendering(): void
{
$grid = $this->getGrid('product');
$this->assertCount(10, $grid->getResults());
}
}
GridFactory and test field types/actions.Driver Mismatch
doctrine/orm without proper repository or class configuration.driver:
name: doctrine/orm
options:
class: App\Entity\Product
repository: '@sylius.repository.product' # Required if not autowirable
Field Type Conflicts
services:
app.grid.field_type.custom:
class: App\Grid\Field\CustomFieldType
tags: [sylius.grid.field_type]
Circular Dependencies in Grids
Product grid filtering by Category grid).lazy loading or ensure grids are defined in a dependency-ordered sequence.Enum Support Quirks
EnumField not displaying choices correctly.fields:
status:
type: enum
options:
choices: ['draft', 'published', 'archived']
enum_class: App\Enum\ProductStatus
Action Route Parameters
routeParameters not passing dynamic values.resource.* placeholders:
actions:
item:
edit:
type: edit
options:
route: app_admin_product_edit
routeParameters:
id: resource.id
How can I help you explore Laravel packages today?