Tables
Description
Tables is the backend engine behind Enso's server-side data tables.
The package reads a JSON table template, validates it, builds the frontend bootstrap payload, turns incoming column and meta state into a normalized request object, applies search and filter pipelines to an Eloquent query, computes row payloads, totals, pagination metadata, and can queue large spreadsheet exports with progress notifications.
It is one of the core Enso infrastructure packages and is designed to be reused by any backend module that exposes list views.
Installation
Install the package:
composer require laravel-enso/tables
Publish the optional assets when you want local overrides:
php artisan vendor:publish --tag=tables-config
php artisan vendor:publish --tag=tables-mail
The package also ships stubs for new table builders, actions, and JSON templates:
php artisan vendor:publish --provider="LaravelEnso\Tables\AppServiceProvider"
When template caching is enabled, clear cached templates on deploy:
php artisan enso:tables:clear
Features
- JSON template DSL for columns, buttons, controls, filters, structure, and styling.
- Dedicated controller traits for init, table data, and Excel export endpoints.
- Search, filter, interval, sort, and pagination normalization through a request/config pipeline.
- Column computors for enums, numbers, dates, datetimes, translations, resources, model methods, and cents.
- Aggregated totals, averages, and custom/raw totals at table level.
- Queue-based spreadsheet exports with chunked fetching, multi-sheet splitting, and mail/database/broadcast notifications.
- Template caching and optional row-count caching for large datasets.
- Extension points for dynamic templates and batch row actions.
- PHPUnit helpers for datatable endpoint testing.
Usage
1. Implement a table builder
Each table builder implements LaravelEnso\Tables\Contracts\Table:
use Illuminate\Database\Eloquent\Builder;
use LaravelEnso\Tables\Contracts\Table;
class Users implements Table
{
public function __construct(private TableRequest $request)
{
}
public function query(): Builder
{
return User::query()->select(['id', 'email', 'is_active']);
}
public function templatePath(): string
{
return __DIR__.'/../Templates/users.json';
}
}
2. Expose the three backend endpoints
The package controller traits are intentionally small:
Initloads the builder and returns the validated template payloadDataapplies request state and returns rows plus metaExcelprepares the queued export flow and emitsExportStarted
use Illuminate\Routing\Controller;
use LaravelEnso\Tables\Traits\Init;
use LaravelEnso\Tables\Traits\Data;
use LaravelEnso\Tables\Traits\Excel;
class InitTable extends Controller
{
use Init;
protected string $tableClass = Users::class;
}
class TableData extends Controller
{
use Data;
protected string $tableClass = Users::class;
}
class ExportExcel extends Controller
{
use Excel;
protected string $tableClass = Users::class;
}
3. Define the JSON template
At minimum, a table template needs:
routePrefixbuttonscolumns
Example:
{
"routePrefix": "administration.users",
"buttons": ["create", "excel"],
"controls": ["columns", "length", "reload", "reset", "style"],
"appends": ["full_name"],
"filters": [
{
"label": "Active",
"data": "users.is_active",
"value": null,
"type": "boolean"
}
],
"columns": [
{
"label": "Email",
"name": "email",
"data": "users.email",
"meta": ["searchable", "sortable"]
},
{
"label": "Balance",
"name": "balance",
"data": "users.balance",
"number": {
"precision": 2,
"symbol": "RON ",
"template": "%s%v"
},
"meta": ["filterable", "total"]
}
]
}
Template structure
Top-level attributes accepted by the validator include:
appends,auth,buttons,controlscomparisonOperator,countCache,crtNodataRouteSuffix,debounce,dtRowIdfilters,flatten,fullInfoRecordLimitlengthMenu,method,model,namepreview,responsive,searchMode,searchModesselectable,strip,templateCachedefaultSort,defaultSortDirection,totalLabel
Column attributes:
- mandatory:
data,label,name - optional:
align,class,dateFormat,enum,meta,number,tooltip,resource
Column meta flags:
average,boolean,clickable,cents,customTotaldate,datetime,filterable,icon,methodnotExportable,nullLast,searchable,rawTotalrogue,slot,sortable,sort:ASC,sort:DESCtotal,translatable,notVisible
Button structure:
- mandatory:
type,icon - types:
global,row,dropdown - actions:
ajax,export,href,router - optional attributes such as
routeSuffix,fullRoute,method,event,postEvent,confirmation,selection,tooltip, andslot
Filters:
- mandatory:
label,data,value,type - optional:
slot,multiple,route,translated,params,pivotParams,custom,selectLabel
Defaults also come from config/tables.php:
- cache behavior
- default buttons and controls
- style mapping
- export queue / sheet limits
- search modes and comparison operators
Request and query pipeline
Incoming frontend state is normalized through:
ProvidesRequestandFilterAggregatorTemplateLoaderandTemplateConfig, which merges request meta onto template columnsData\Builders\Data,Meta, andTotal
The data pipeline applies:
- global search
- per-column filters
- numeric and date intervals
- default and custom sorting
- pagination limits
- model and array computors
- row actions and row style metadata
Computors and formatting
The package supports two families of computors:
- model computors such as
methodandresource - array computors such as
enum,number,date,datetime,cents, andtranslator
That lets you:
- render enum labels from legacy Enso enums or native PHP enums
- format numbers with symbols and precision
- format dates using the configured global or per-column format
- call model methods for derived values
- wrap values in API resources before returning them
Export flow
The export endpoint uses Prepare, then queues either Jobs\Excel or Jobs\EnsoExcel.
During export the package:
- rebuilds the filtered query
- streams rows in chunks through
Fetcher - writes one or more sheets with OpenSpout
- stores the file under
storage/app/{export.folder} - notifies the user with
ExportStarted,ExportDone, orExportError
Caching and extension points
TemplateLoadercaches cacheable template fragments by template path, pluscachePrefix()when the table implementsDynamicTemplateTableCachecan invalidate cached counts on model create/delete- custom batch jobs can extend
LaravelEnso\Tables\Services\Action
Tests
The package ships focused unit coverage for:
- template builders and validators
- search, filter, interval, meta, and export builders
- template cache loading
TableCacheinvalidation behavior
Useful local targets:
php artisan test --compact vendor/laravel-enso/tables/tests/units/Services/TemplateLoaderTest.php
php artisan test --compact vendor/laravel-enso/tables/tests/units/Traits/TableCacheTest.php
API
The package exposes three backend endpoints through the controller traits documented in the usage flow:
Initreturns the validated template payload and frontend bootstrap metadataDataresolves the request pipeline and returns rows, totals, pagination, and table metaExcelstarts queued spreadsheet exports and emits the export-start event
At code level, the stable backend contract is LaravelEnso\Tables\Contracts\Table. Custom table builders should implement query() and templatePath(), while downstream modules should treat helper classes such as processors, calculators, computors, and normalizers as internal implementation details unless they are extended deliberately.
Depends On
Required Enso packages:
Companion frontend package:
Contributions
are welcome. Pull requests are great, but issues are good too.
Thank you to all the people who already contributed to Enso!