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

Grid Bundle Laravel Package

intonation/grid-bundle

A Symfony/PHP bundle for defining configurable data grids in code: declare columns, sorting, filtering, and pagination, then render them through templates. A practical starting point for admin tables and record listings, with room to customize how data is sourced and displayed.

View on GitHub
Deep Wiki
Context7

Getting Started

The package wires up automatically via Laravel's package discovery; the only required step is composer require plus (if you want to tweak defaults) php artisan vendor:publish --tag=grid-config. No migrations are shipped — the grid library is metadata only and reads entities you already have.

Where to look first:

  1. README.md quickstart — v0.2 rewrote this and it is now the fastest path to a working grid.
  2. config/grid.php — element/column guesser registration order, default pagination size, filter namespace.
  3. src/Grid/GridType — the base class/contract you extend for every grid.
  4. src/Grid/GridService.php — the new createGridFromEntity entry point.

First use case — a read-only admin listing:

// app/Grid/UserGridType.php
class UserGridType extends AbstractGridType
{
    public function buildGrid(GridBuilder $builder): void
    {
        $builder
            ->addColumn('id', IntegerType::class)
            ->addColumn('email', TextType::class)
            ->addColumn('created_at', DateTimeType::class)
            ->addFilter('email', TextType::class);
    }
}
Route::get('/admin/users', fn (GridService $grids) =>
    view('admin.users', ['grid' => $grids->createGrid('user_grid')])
);

For scaffolding, the new GridService::createGridFromEntity(User::class) gives you a usable grid with zero configuration — columns are derived from the entity, filters are inferred, and element types are resolved through ElementTypeGuesser. Use it to prototype, then promote to an explicit GridType once requirements firm up.

Implementation Patterns

Explicit GridType per screen (recommended default). Register the type in config/grid.php (or via the service provider's registerGridType) and resolve it with GridService::createGrid('user_grid'). Keeps column/filter definitions testable and reviewable in isolation.

Entity-derived grids for internal tooling. createGridFromEntity is ideal for back-office tables where you control the schema but not the UI spec — CRUD scaffolds, generated admin panels, per-tenant tables built from a runtime entity list. Pair it with a small override callback (or a GridBuilder decorator) for the handful of columns that need custom rendering:

$grid = $grids->createGridFromEntity(Order::class);
$grid->getColumn('status')->setOptions(['format' => 'badge']);

Customizing element/column guessing. ElementTypeGuesser centralizes the "PHP type → form/grid element" mapping. Extend or decorate it and register with a priority higher than the built-in guessers when you need custom types (e.g. Money → a currency-aware column, Enum → a select filter with the enum cases). Keep custom guessers stateless — they're called for every column and filter.

Controller shape. Inject GridService rather than constructing grids inline; keep the action to three lines (create grid → handleRequest → return view/JSON). For AJAX-filtered tables, return the grid's data as JSON on X-Requested-With and render the full page otherwise — one endpoint, two responses.

Layer for reuse. If several grids share columns (timestamps, soft-delete badge, audit columns), compose them via a GridType trait or a GridBuilder decorator instead of duplicating the addColumn calls.

Testing. Unit-test buildGrid by asserting columns/filters/types on the builder output; functional-test the endpoint for filtering, sorting and pagination boundaries. For createGridFromEntity, assert against a factory-created model so schema drift is caught in CI.

Gotchas and Tips

  • Guesser ordering matters. Guessers are consulted in registration order and the first match wins. A custom ElementTypeGuesser registered after the defaults is dead code — set a priority or register before the package provider.
  • Entity-derived grids are inference, not magic. Relations, accessors, and virtual/computed fields generally won't be picked up; add them explicitly. Check the generated grid before shipping — inferred columns silently reflect whatever metadata is available.
  • Watch for N+1. A column bound to a relation will lazy-load per row. Eager-load via the grid's query builder ($builder->setQueryBuilder(fn ($q) => $q->with('customer'))) rather than in the controller.
  • Sorting whitelist. Only allow sortable flags on known columns; never forward the sort query param straight into orderBy. Inferred grids in particular can expose join aliases you didn't intend.
  • Filter parameter naming. Filters bind from the request by name; with dynamic grids the names come from generated columns, so a renamed entity column becomes a silent no-op filter. Log unknown filter params in development.
  • Element type changes between versions. v0.2's ElementTypeGuesser can change the resolved type for previously inferred columns (e.g. a DateTime field that used to fall back to a text input now resolving to a date picker). If a screen's filters or renderers are sensitive, pin the element type explicitly in the addColumn/addFilter call.
  • Debugging an invisible grid. Dump the resolved definition ($grid->getDefinition() or the equivalent) and confirm the type is registered and the name matches config; a missing registration usually surfaces as an empty or exception-throwing grid rather than a clear error.
  • Cache deliberately. Definitions are rebuilt per request; if your grid types are expensive (many reflection calls, DB-backed enums), cache the built definition keyed by entity + user role, and bust on deploy — schema changes won't invalidate it automatically.
  • Extension point to prefer. For per-screen tweaks, decorate the built grid (or pass an options array to createGridFromEntity) rather than subclassing GridService — the service is the package's most likely surface to change in 0.x releases.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource