Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Tablebundle Laravel Package

jgm/tablebundle

A PHP/Symfony bundle for building and rendering data tables from arrays or query results, with configurable columns, sorting, pagination, and Twig templates for flexible, reusable table output.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — there is no service provider, no facade, and no config/tablebundle.php. Before writing a line of code, decide whether you are (a) working in a legacy Symfony 2/3 app where you can adopt it directly, or (b) trying to port the idea of server-rendered tables into a Laravel app. Only (a) is a realistic "day-to-day" use; for (b) you are really reading this repo as reference material.

Minimal steps in a Symfony host app:

  1. composer require jgm/tablebundle (expect to pin old Symfony/Doctrine constraints; the last tagged release is from 2016-08-18 and the repo is archived, so dependency resolution against a modern Symfony will almost certainly fail without --ignore-platform-reqs tricks or a fork).
  2. Register the bundle in app/AppKernel.php (new JGM\TableBundle\TableBundle()), and confirm the Twig bundle is present — this package is Twig-first by design.
  3. Look first at the bundle's Table/ directory (the TableBuilder/Table/column classes) and at Resources/views/ for the default templates. Those two places tell you everything about the public API and the markup contract.
  4. First use case: a server-rendered, sortable, paginated list — the classic "no JavaScript" admin index. Define a table, bind it to a Doctrine query, render it in a Twig template, and let query-string parameters (page, sort, order) drive state on the next request.

Implementation Patterns

The core workflow is: describe the table once, render it anywhere, let the request drive it.

  • Table definition as a class. The idiomatic pattern is a reusable table type/definition class (analogous to a Symfony form type) that declares columns, labels, sortable flags, and the data source. Keep the definition out of the controller so the same table can be reused on an index page, a dashboard widget, and an export.
  • Query builder binding. Tables are fed a Doctrine QueryBuilder. Build the query with your filters first, hand it to the table, and let the bundle apply ordering and limit/offset. Do not getResult() yourself before handing it over, or pagination counts will be wrong.
  • Request-driven state. Pagination and sorting ride on query-string parameters. That means every table interaction is a full page load — which is the whole point (works without JS, cacheable, printable), but it also means your controller must be tolerant of arbitrary query params.
  • Twig rendering. Render via the bundle's Twig function/block and override the shipped templates rather than editing vendor files. Template overrides are the sanctioned extension point for markup, CSS classes, and empty-state rows.
  • Composition over monolith. For dashboards, mount several small tables rather than one giant one; each gets its own query and its own pagination param namespace (prefix them, e.g. orders_page vs users_page, so two tables on one page don't fight over page).
  • Laravel-side analogue. If you're mining this for a Laravel app, the transferable pattern is: a Table value object built from a Builder, column definitions with sortable()/label(), a ->paginate() that reads request('sort') against an allowlist, and a Blade partial. That is roughly 200 lines of code and you own it — which, given the archived status, is the better trade.

Gotchas and Tips

  • It is archived and unmaintained. No security patches, no PHP 8 / Symfony 5+ support, no compatibility guarantees. Treat any adoption as forking the code into your own namespace.
  • Zero Laravel interoperability. No service provider, no container bindings, no Blade. The Twig dependency alone makes direct reuse in a Laravel app impractical — you'd be pulling Twig in alongside Blade.
  • Sort column injection. Anything driven by a raw sort query parameter is an injection surface if the column name isn't validated against the declared column allowlist. Verify the bundle does this; if not, wrap it before it reaches the query builder.
  • ORDER BY and pagination on joins. With Doctrine queries that join one-to-many relations, LIMIT/OFFSET counts rows, not entities — you will see duplicate or short pages. Use a distinct-root-entity query or two-step ID pagination.
  • Pagination counts are expensive. A COUNT(*) on a heavy filtered query is often slower than the page fetch itself. For big tables, cap the count or use an approximate/estimated total.
  • Query-param collisions. Multiple tables on one page is the most common real-world bug; namespace the params per table instance.
  • PHP version drift. Code from the 2016 era will hit deprecated constructs and strict-type surprises under PHP 7.4+. Expect a small modernization pass (nullable types, [] array syntax, removal of each()-style patterns) before it runs cleanly.
  • Debugging rendering issues. Start by dumping the table object before render() — column registration, sort state, and row count are usually wrong there rather than in the template. Then check the resolved Twig template path, since overrides silently fall back.
  • Extension points worth knowing: template overrides, custom column renderers, and subclassing the table/definition class. There is no event dispatcher integration worth relying on.
  • Bottom line for a Laravel developer: don't install it. Read the column/query-binding design, then implement a small first-party table helper — it will be less code than the workaround layer you'd need to make a 2016 Symfony bundle behave.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo