victorbalssa/datatables-bundle-with-regex
A Symfony DataTables bundle with regex-enabled filtering for advanced server-side search. It extends standard DataTables query controls so you can match complex patterns and build more flexible data grids.
This is a fork/wrapper of the DataTables server-side bundle with added regex filtering support, shipped at 0.8.x — pre-1.0, so treat the API as unstable.
composer require victorbalssa/datatables-bundle-with-regex:0.8.1 (pin the patch, see Gotchas). If your Laravel version doesn't auto-discover the service provider, add it manually to config/app.php. Then publish the config:
php artisan vendor:publish --tag=datatables
php artisan config:clear
DataTable base class — that class is the extension point you'll subclass once per table. Check the adapter namespace too: whether you get an ORM/Doctrine adapter, a query-builder adapter, or an array adapter determines everything downstream.php artisan make: isn't provided, so hand-write a class extending the base, declare your columns, then point it at a query source:
class UsersTable extends AbstractDataTable
{
public function build(): static
{
return $this->add('id', 'u.id')
->add('name', 'u.name')
->add('email', 'u.email')
->createAdapter(/* ORM or QueryBuilder source */);
}
}
$table->handleRequest() (JSON for DataTables' ajax), a route points at it, and the Blade view renders the <table> plus the standard $('#users').DataTable({ serverSide: true, processing: true, ajax: '...' }) init. Put the route behind auth middleware from the very first commit — an unguarded DataTables endpoint is a full table dump.The fastest sanity check is a two-column table over a table with <100 rows: if recordsTotal looks right and sorting toggles, your adapter and column-to-DB mapping are correct, and everything else is incremental.
One DataTable class per resource, kept thin. Configure columns and the adapter in the class; keep request-derived filtering (tenant id, date range, "my records only") in a service or via container injection so the table stays testable. Injecting the authenticated user or a filter DTO into build() is the cleanest way to scope rows without touching the controller.
Column declaration drives everything. Each add() maps a front-end data key to a DB column/alias. Set searchable/sortable flags explicitly rather than relying on defaults — it prevents accidental full-table LIKE scans on wide text columns and accidental ordering on unindexed columns.
Regex search is the differentiator, so use it deliberately. Two patterns work well:
regex: true only on the specific columns where users need pattern matching (SKUs, prefixed IDs, log codes) via columns[i].search.regex = true in JS, and mark only those columns searchable.regex: true, giving users a documented mini-language rather than a raw regex box on every field.Keep the regex column count small and the underlying columns indexed. A regex filter is a non-sargable predicate — it will seq-scan, so pair it with a mandatory date range or tenant scope.
Adapter choice is an architectural decision, not a detail. If the bundle's adapter is ORM/Doctrine-flavoured, wrapping Eloquent means converting to the query builder or using the raw/array adapter. Whichever you pick, do it once in a base class (App\Support\DataTables\BaseTable) so a future 0.9/1.0 adapter change is a one-file edit.
Formatters belong in the table, not the view. Use the column render/formatter hook to emit action buttons, statuses, and dates. Emit pre-escaped HTML or structured JSON consistently — half-escaped cells are the most common XSS vector in DataTables apps.
Testing. Hit the AJAX route in a feature test with DataTables' query params (draw, start, length, columns[...], search[value]) and assert on draw, recordsTotal, recordsFiltered, and the shape of a row. Add one test per adapter filter, and one specifically for a regex column — that's the code path this fork exists for.
Version discipline. Because this is a 0.8.x fork, treat the lockfile as load-bearing and add a composer outdated review step before bumping. Diff every release with git compare — as in 0.8.1, the release notes may be nothing but a compare link.
0.8.0...0.8.1 yourself before upgrading and pin "victorbalssa/datatables-bundle-with-regex": "0.8.1" rather than ^0.8 if you're in production. Pre-1.0 semver gives you nothing.regex: true globally on all columns.REGEXP, PostgreSQL ~, and SQLite (no native regex) do not behave identically. If the package translates regex to LIKE for non-supporting adapters, your tests will pass on MySQL and silently degrade elsewhere. Verify on your actual driver.recordsFiltered ≠ recordsTotal once you join. One-to-many joins duplicate rows and break counts. Use distinct on the primary key and verify both counts on a joined table before shipping.data keys exactly, including join ambiguity (u.id vs id). Mismatched names fail silently — the column renders empty with no error in the console.php artisan config:clear; otherwise a stale cached config makes your adapter edits appear ignored.LIMIT/OFFSET degrades on deep pagination; if the bundle only offers offset paging, keep default page sizes small and push heavy consumers onto filtered queries via the regex/date filters rather than page 500.handleRequest entry point if you need to wrap the JSON response in a policy check or audit log.Log::debug in the controller). Nearly every "wrong results" bug is either a column-mapping mismatch or a filter applied to the wrong column index.How can I help you explore Laravel packages today?