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

pedro-teixeira/grid-bundle

A Symfony bundle for building data grids from Doctrine entities with sortable columns, filters, pagination, bulk actions, and CSV/Excel export. Configure columns, search, and row actions quickly in PHP or annotations for admin and reporting screens.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: pedro-teixeira/grid-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/grid.php, and its renderer is Twig-based. Last tagged release was 2015-03-31, so it targets Symfony 2.x and PHP 5.x-era components. For a Laravel developer, "leveraging" this package almost always means mining it for its grid architecture and re-implementing that structure in Laravel idioms — not composer require-ing it into a Laravel app.

Steps:

  1. Try the install only to confirm viability. composer require pedro-teixeira/grid-bundle will almost certainly fail dependency resolution against Laravel 10/11 (which require symfony/* v6/v7) because the bundle pins old Symfony constraints. Don't burn time on --ignore-platform-reqs gymnastics in a real app.
  2. Read the source, not the docs. The repo is small; the useful artifacts are the Grid definition class, the Column classes (including subclasses for custom rendering), and the builder/factory that assembles them. That's your spec.
  3. Port the concepts into a app/Support/Grid namespace. One class per table, columns declared in code, data source injected — that's the whole idea, and it translates cleanly to Laravel.
  4. First use case: the admin index page you've written three times already. Build one UsersGrid class, render it in Blade, and compare line count against your previous hand-rolled <table>.

If you genuinely need a maintained grid/table package in Laravel today, evaluate Filament Tables, Orchid, or a Livewire table component instead — and treat grid-bundle as an architectural reference (MIT licensed, so copying patterns or even classes with attribution is fine).

Implementation Patterns

Grid-as-a-class (the core pattern worth stealing). The bundle's value is that column definitions are objects, not template conditionals. Mirror it:

// app/Support/Grid/UsersGrid.php
class UsersGrid extends Grid
{
    public function columns(): array
    {
        return [
            TextColumn::make('id')->sortable(),
            TextColumn::make('name')->searchable(),
            TextColumn::make('email'),
            DateColumn::make('created_at')->format('Y-m-d'),
            ActionColumn::make()->actions([
                'edit'   => fn ($row) => route('admin.users.edit', $row),
                'delete' => fn ($row) => route('admin.users.destroy', $row),
            ]),
        ];
    }

    public function query(): Builder
    {
        return User::query()->with('roles'); // eager load here, not in the view
    }
}

Value resolution via data_get(). The Symfony original resolves column values by property/accessor. In Laravel use closures plus data_get($row, $path) so nested paths (roles.0.name) and array rows both work without special-casing Eloquent vs. arrays.

Rendering as a Blade component. The bundle ships Twig templates; replace them with <x-grid :grid="$grid" /> that loops $grid->columns() and calls $column->render($row). Keep escaping in the component, not in the column classes — same separation the bundle gives you.

Actions column with authorization. The bundle's "extensible columns and actions" maps to closures that return a URL, plus a canSee closure checked against Gate::allows(). Doing the auth check here (server-side, once) beats scattering @can in Blade — and it makes the action set testable.

Filters and sorting from the request. Keep a whitelist derived from column metadata (->sortable(), ->searchable()) and apply it to the query builder. Never trust ?sort= directly — the whole point of declaring columns is that the column list is your allowlist.

Data source swap: Doctrine → Eloquent. The bundle expects a Doctrine-backed collection. Your port should accept Illuminate\Contracts\Pagination\LengthAwarePaginator so the grid can render its own pagination links and withQueryString(). If you go Inertia or Livewire, keep the grid class as the single source of truth and serialize columns to an array for the frontend.

Extension points. Copy the abstract-column-per-type structure: one base Column with render()/header()/sortKey(), subclasses for Text, Date, Badge, Action, and a ColumnFactory if you want config-driven columns later. This is the piece that pays off — new column types without touching the grid templates.

Gotchas and Tips

  • No Laravel integration exists, and none is coming. Don't design a feature around this package's runtime. Design around its shape.
  • Symfony DI assumptions won't survive. The bundle uses services.yml, tagged services, and GridBuilder autowiring. Laravel's container has no tag system; bind your grids explicitly ($this->app->bind(UsersGrid::class)) or instantiate them in controllers. If you copy classes wholesale, strip the ContainerAware/AbstractController inheritance first.
  • OptionsResolver is a Symfony dependency. If you want option validation with defaults in your ported columns, use a small hand-rolled $defaults + $options merge or Laravel's Validator; don't drag symfony/options-resolver in just for this (you already have it, but the 2015 API differs from current).
  • Old PHP syntax. Expect no return types, no scalar type hints, possibly deprecated constructs. If you copy code, run Rector or add types manually before PHPStan level 5+ will pass.
  • Twig autoescape has no Blade equivalent for HTML columns. {{ }} escapes, {!! !!} doesn't. Give HTML-rendering columns an explicit ->html() flag so reviewers can see where raw output is intentional — this is exactly where XSS creeps into ported grid code.
  • The grid can't see your N+1s. The original's data source was already-loaded Doctrine collections; an Eloquent port will lazy-load relations per cell unless you eager-load in query(). Enable Model::preventLazyLoading() in local to catch it.
  • Pagination and sort state live in the URL. Use withQueryString() and preserve filter params in action URLs, or users lose context after an edit redirect — the bundle's Twig templates handle this implicitly, so it's easy to drop when porting.
  • Test the columns, not the HTML. Unit-test value resolvers and canSee closures; one HTTP test to assert the grid renders. Asserting on table markup makes every CSS tweak a test failure.
  • Keep attribution. MIT allows reuse; a short comment pointing at the original repo in your app/Support/Grid namespace is cheap and avoids awkwardness later.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource