sylius/grid
Sylius Grid component adds a reusable, configurable grid system for Symfony apps. Define grids in configuration, plug in data providers and drivers, then render sortable, filterable tables with pagination and actions—ideal for admin panels and back-office listings.
Installation Add the package via Composer:
composer require sylius/grid
Publish the configuration (if needed):
php artisan vendor:publish --provider="Sylius\Grid\GridServiceProvider"
Basic Usage
Define a grid in a service class (e.g., ProductGrid):
use Sylius\Grid\Grid;
use Sylius\Grid\GridDefinition;
use Sylius\Grid\GridInterface;
class ProductGrid implements GridInterface
{
public function getDefinition(): GridDefinition
{
return GridDefinition::create()
->setSource(new ProductSource()) // Custom source class
->addField('name')
->addField('price')
->addSorting('name', 'price')
->addFilter('name', 'contains')
->addAction('edit', 'Edit', '/products/{id}/edit');
}
}
First Use Case Inject the grid into a controller and render it in a view:
use Sylius\Grid\GridRenderer;
class ProductController
{
public function index(GridRenderer $gridRenderer, ProductGrid $productGrid)
{
return $gridRenderer->render($productGrid);
}
}
Grid Definition
addField('name')->setLabel('Product Name')).addSorting('field', 'direction') (e.g., addSorting('price', 'desc')).addFilter('price', 'gt', 100)).addAction('view', 'View', '/products/{id}')).Custom Sources
Extend AbstractSource to fetch data:
use Sylius\Grid\Source\AbstractSource;
class ProductSource extends AbstractSource
{
public function getEntities(string $direction = null, ?int $offset = null, ?int $limit = null)
{
return ProductRepository::all()->paginate($limit, $offset);
}
}
Dynamic Grids
Use GridDefinition::create()->setSource(new DynamicSource($context)) for runtime configurations.
Twig Integration Render grids in views with:
{{ render(controller('Sylius\Grid\GridRenderer', {grid: productGrid})) }}
GridRenderer with JsonResponse for JSON output.GridEvent for pre/post-processing (e.g., GridEvent::PRE_LOAD).Source Mismatch
getEntities() returns a Collection or Paginator compatible with pagination.Collection if needed:
return new Collection($rawResults);
Filter Operator Conflicts
in, not_in) require explicit type hints in addFilter().addFilter('field', 'operator', $value, $type) with FilterType::STRING, FilterType::NUMERIC, etc.Sorting Ambiguity
name in relations) may break sorting.addSorting('product.name')).Caching Issues
php artisan cache:clear
GridEvent::PRE_LOAD:
public function onPreLoad(GridEvent $event) {
\Log::debug('Grid data:', $event->getGrid()->getSource()->getEntities());
}
config/grid.php for custom settings (e.g., default_limit).Custom Filters
Extend AbstractFilter and register via GridServiceProvider:
$this->grid->addFilterType('custom', CustomFilter::class);
Override Rendering
Replace the default renderer by binding a custom GridRenderer:
$this->app->bind(GridRenderer::class, CustomGridRenderer::class);
Dynamic Field Mapping
Use FieldDefinition::setMapper() to transform data before rendering:
->addField('price')
->setMapper(function ($value) {
return '$' . number_format($value, 2);
})
How can I help you explore Laravel packages today?