ali/datatable
Symfony2 bundle integrating jQuery DataTables with Doctrine entities and Bootstrap styling. Provides a datatable service, Twig helpers, dynamic paging, column search, association/query builder support, custom renderers, grouped actions, and optional default edit/delete links.
Installation:
composer require ali/datatable
Add to AppKernel.php:
new Ali\DatatableBundle\AliDatatableBundle(),
Enable Twig Extension:
Ensure AliDatatableBundle is registered in config.yml:
twig:
extensions: [Ali\DatatableBundle\Twig\Extension\DatatableExtension]
First Use Case:
Create a basic datatable for an entity (e.g., User):
{{ datatable(
'user_datatable',
'AppBundle:User',
{
'columns': [
{ 'name': 'id', 'label': 'ID' },
{ 'name': 'username', 'label': 'Username' },
{ 'name': 'email', 'label': 'Email' }
]
}
) }}
Route Configuration:
Define a route for the datatable AJAX endpoint in routing.yml:
ali_datatable:
resource: "@AliDatatableBundle/Resources/config/routing.yml"
prefix: /
Entity Integration:
Use the datatable() Twig function to bind a Doctrine entity to a jQuery DataTable:
{{ datatable(
'entity_datatable',
'AppBundle:User',
{
'columns': [
{ 'name': 'id', 'label': 'ID' },
{ 'name': 'createdAt', 'label': 'Created At', 'type': 'datetime' }
],
'actions': [
{ 'type': 'edit', 'route': 'edit_user', 'routeParams': { 'id': 'id' } },
{ 'type': 'delete', 'route': 'delete_user', 'routeParams': { 'id': 'id' } }
]
}
) }}
Dynamic Query Building: Extend the default query via a service or controller:
// services.yml
services:
app.user_datatable:
class: Ali\DatatableBundle\Service\DatatableService
arguments:
- '@doctrine.orm.entity_manager'
- 'AppBundle:User'
- '@router'
tags:
- { name: ali.datatable, alias: user_datatable }
Custom Rendering: Override column rendering with Twig closures:
{ 'name': 'status', 'label': 'Status', 'renderer': 'renderStatus' }
Define the Twig function in your template:
{% function renderStatus(value) %}
{% if value == 1 %}
<span class="label label-success">Active</span>
{% else %}
<span class="label label-danger">Inactive</span>
{% endif %}
{% endfunction %}
Grouped Actions: Add bulk actions (e.g., delete, export):
{{ datatable(
'user_datatable',
'AppBundle:User',
{
'groupedActions': [
{ 'type': 'delete', 'label': 'Delete Selected', 'route': 'bulk_delete_users' }
]
}
) }}
JavaScript Integration: The bundle auto-generates and minifies JS. Customize via config:
ali_datatable:
javascript:
enabled: true
options:
processing: true
serverSide: true
ajax: { url: '{{ path('ali_datatable_user') }}' }
Laravel Adaptation:
Since this is a Symfony bundle, use Laravel’s Symfony Bridge or Kirkbusch/DoctrineBundle for compatibility. Replace AppKernel.php logic with Laravel service providers.
Example provider:
namespace App\Providers;
use Ali\DatatableBundle\AliDatatableBundle;
use Illuminate\Support\ServiceProvider;
class DatatableServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->register(new AliDatatableBundle());
}
}
Blade Template Integration:
Extend Twig’s datatable() function in Laravel using a custom Blade directive:
// app/Providers/BladeServiceProvider.php
Blade::directive('datatable', function ($expression) {
return "<?php echo \\Ali\\DatatableBundle\\Twig\\Extension\\DatatableExtension::renderDatatable($expression); ?>";
});
Usage in Blade:
@datatable('user_datatable', 'AppBundle:User', { /* config */ })
API-Driven Tables: For SPAs, use the bundle’s AJAX endpoint to fetch data via Laravel’s API routes:
Route::get('/api/users', 'DatatableController@getUsers')->name('ali_datatable_user');
Symfony Dependency:
EntityManager and Twig. In Laravel, mock these dependencies or use a bridge (e.g., kirkbusch/doctrine-bundle).DatatableService to work with Laravel’s EntityManager:
$this->app->bind('ali.datatable.service', function ($app) {
return new \Ali\DatatableBundle\Service\DatatableService(
$app['doctrine.orm.entity_manager'],
'AppBundle:User',
$app['router']
);
});
Route Conflicts:
ali_datatable_*) may clash with Laravel’s naming.routes/web.php:
Route::get('/datatable/users', 'DatatableController@index')->name('custom_datatable_user');
JavaScript Minification:
ali_datatable:
javascript:
enabled: false
Manually include the generated JS in your layout:
{!! \Ali\DatatableBundle\Twig\Extension\DatatableExtension::getJavascript('user_datatable') !!}
Association Handling:
user.posts.title) require explicit DQL or custom query builders.QueryBuilder in the service:
$qb = $this->entityManager->getRepository('AppBundle:User')->createQueryBuilder('u');
$qb->leftJoin('u.posts', 'p');
return $qb->getQuery();
Twig Extension Conflicts:
Blade, Twig extensions may not auto-load.AppServiceProvider:
$twig = $this->app['view']->getEngine();
$twig->addExtension(new \Ali\DatatableBundle\Twig\Extension\DatatableExtension());
Check Generated SQL:
Enable Doctrine logging in config/app.php:
'debug' => env('APP_DEBUG', true),
Inspect SQL queries in Laravel’s log (storage/logs/laravel.log).
Validate JSON Responses: The bundle returns JSON for AJAX requests. Validate with:
curl -X POST http://your-app.test/datatable/users -H "Content-Type: application/json"
Expected response structure:
{
"data": [...],
"recordsTotal": 100,
"recordsFiltered": 50
}
Inspect JavaScript: Disable minification to debug JS:
ali_datatable:
javascript:
options:
ajax: { url: '{{ route('custom_datatable_user') }}', 'dataSrc': '' }
Use browser dev tools to check for 404s or syntax errors.
Custom Query Builders:
Extend the DatatableService to support custom queries:
namespace App\Services;
use Ali\DatatableBundle\Service\DatatableService as BaseService;
class CustomDatatableService extends BaseService
{
protected function buildQuery()
{
$qb = parent::buildQuery();
// Add custom logic (e.g., soft deletes)
$qb->andWhere('u.deletedAt IS NULL');
return $qb;
}
}
Dynamic Column Configuration: Fetch columns from the database (e.g., for dynamic forms):
{% set columns = attribute(app
How can I help you explore Laravel packages today?