Installation
composer require sg/datatablesbundle
Add to bundles.php (Symfony <5.0) or config/bundles.php (Symfony ≥5.0):
return [
// ...
Sg\DataTablesBundle\SgDataTablesBundle::class => ['all' => true],
];
Basic Controller Usage
Create a controller with a getDataTablesData() method:
use Sg\DataTablesBundle\DataTables;
use Sg\DataTablesBundle\DataTables\DataTablesFactory;
class MyController extends Controller
{
public function myAction(DataTablesFactory $factory)
{
$dataTables = $factory->createStandardDataTable();
$dataTables->setEntityClass('App\Entity\MyEntity');
return $dataTables->getDataTablesData();
}
}
First Template Integration
Use the datatables Twig helper in your template:
{{ datatables({
'src': path('my_route'),
'columns': [
{ 'data': 'id' },
{ 'data': 'name' },
{ 'data': 'email' }
]
}) }}
$dataTables = $factory->createStandardDataTable();
$dataTables->setEntityClass('App\Entity\User');
$dataTables->setSearchableColumns(['firstName', 'lastName', 'email']);
$dataTables->setOrderableColumns(['firstName', 'lastName', 'createdAt']);
$dataTables = $factory->createStandardDataTable();
$dataTables->setEntityClass('App\Entity\Order');
$dataTables->setQueryBuilder(function (QueryBuilder $qb) {
$qb->andWhere('o.status = :status')
->setParameter('status', 'pending');
});
$dataTables->setColumns([
'id' => [
'title' => 'ID',
'width' => '5%',
'render' => function ($value) {
return '<a href="/orders/' . $value . '">' . $value . '</a>';
}
],
'total' => [
'title' => 'Total',
'render' => function ($value, $row) {
return '$' . number_format($value, 2);
}
]
]);
$dataTables = $factory->createStandardDataTable();
$dataTables->setEntityClass('App\Entity\Product');
$dataTables->setServerSide(true); // Enable server-side processing
{{ form_start(form) }}
{{ form_widget(form) }}
{{ datatables({
'src': path('product_datatable'),
'columns': columns,
'serverSide': true,
'ajax': {
'data': function(d) {
d.custom_param = $('#my_form').serialize();
return d;
}
}
}) }}
{{ form_end(form) }}
$dataTables = $factory->createStandardDataTable();
$dataTables->setEntityClassResolver(function (Request $request) {
$entity = $request->query->get('entity');
return 'App\Entity\\' . ucfirst($entity);
});
$dataTables->setActions([
'edit' => [
'title' => 'Edit',
'url' => function ($row) {
return path('edit_product', ['id' => $row['id']]);
}
],
'delete' => [
'title' => 'Delete',
'class' => 'btn-danger',
'url' => function ($row) {
return path('delete_product', ['id' => $row['id']]);
},
'confirm' => 'Are you sure?'
]
]);
$dataTables->addListener('preProcess', function (DataTables $dataTables) {
$dataTables->setSearchableColumns(['name', 'description']);
});
$dataTables->setExportable(true);
$dataTables->setExportColumns(['id', 'name', 'price']);
Deprecated Methods
setDataTable(); use setEntityClass() or setQueryBuilder() instead.setColumns() now expects an associative array, not a simple array.Query Builder Conflicts
QueryBuilder includes all necessary JOINs and WHERE clauses for filtering, sorting, and pagination to work correctly.// ❌ Missing JOIN for related entities
$qb->select('u.id, u.name');
// ✅ Include all necessary fields and relations
$qb->select('u.id, u.name, a.address')
->leftJoin('u.address', 'a');
Server-Side Processing Overhead
setServerSide(true)) can be resource-intensive. Optimize with:
->leftJoin()->addSelect()).Twig Template Issues
sg_datatables Twig extension is loaded. If using Symfony Flex, this should be automatic.{# ✅ Safe rendering #}
{{- datatables_column('name', 'render')|e('html_attr') -}}
Caching Headaches
Enable Query Logging
Add to config/packages/dev/doctrine.yaml:
doctrine:
dbal:
logging: true
profiling: true
Check logs for generated SQL queries to verify filtering/sorting/pagination.
Inspect Request Data Dump the incoming request data to ensure DataTables parameters are received:
public function myAction(Request $request, DataTablesFactory $factory)
{
dump($request->query->all());
// ...
}
Validate Column Names
Ensure column names in setColumns() match the entity properties or aliases in your QueryBuilder.
Check for Deprecated Features The bundle is unmaintained; test thoroughly if using features not documented in the latest release (2022-03-03).
Custom Data Providers
Implement Sg\DataTablesBundle\DataTables\DataProviderInterface for non-Doctrine data sources:
class CustomDataProvider implements DataProviderInterface
{
public function count($request)
{
// Return total count
}
public function fetch($request)
{
// Return filtered/sorted/paginated data
}
}
Register with:
$dataTables->setDataProvider($customProvider);
Override Twig Helpers
Extend the Twig environment to customize the datatables function:
$twig->addFunction(new \Twig\TwigFunction('custom_datatables', function ($options) {
// Custom logic
return new \Twig\Markup($html, 'UTF-8');
}));
Add Custom JavaScript Extend the default DataTables initialization:
{{ datatables({
'src': path('my_route'),
'js': [
'dataTables.ext.js',
'custom_script.js'
],
'initComplete': 'function() { console.log("Initialized!"); }'
}) }}
Integrate with API Platform Use the bundle for server-side processing while leveraging API Platform for entity management:
$dataTables->setEntityClass('ApiPlatform\Entity\Product');
$dataTables->setPaginationEnabled(false); // Use API Platform's pagination
Default Values
setServerSide(false) by default (client-side processing).setSearchableColumns([]) means no columns are searchable unless specified.setOrderableColumns([]) disables sorting unless columns are defined.Localization
How can I help you explore Laravel packages today?