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

Datagrid Bundle Laravel Package

firano/datagrid-bundle

firano/datagrid-bundle is a data grid package for PHP/Laravel apps that helps you build sortable, searchable tables with reusable columns, filters, pagination, and configurable actions, making admin listings and reports faster to implement.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by accepting the constraint: this is not a Laravel package. firano/datagrid-bundle is a Symfony 2 bundle (NeutronDataGridBundle) that wires the jqGrid jQuery plugin into a Symfony kernel via DI container, bundle registration, and Twig helpers. There is no service provider, no facade, no Blade integration. composer require will download code that nothing in a Laravel app bootstraps.

So "getting started" means treating the repo as a specification, not a dependency:

  1. Do not add it to composer.json. Clone the repo locally or browse it on GitHub instead.
  2. Read the request/response contract. Look at the controller that returns JSON, and the base grid class under DataGrid/. These two files are the entire usable surface area. Note how page, rows, sidx, sord, _search, and filters are read and translated into a query, and how the response envelope (page, total, records, rows) is assembled.
  3. Write the contract down as an internal spec — the exact request params accepted and the exact JSON shape returned. This is the deliverable, more than any code.
  4. Build your first grid in Laravel against that spec: one Eloquent model, one controller with a data() action, one Blade view with a <table> and a jQuery/jqGrid init block (or a modern table component — see below).

Where to look first, in order:

  • The JSON-returning controller — this is the contract you must reproduce.
  • The base grid/column-definition class — this shows the request-param → query translation (limit/offset/orderBy).
  • Resources/public — the bundled jqGrid JS/CSS assets; confirms the jQuery-era front-end this was built for.
  • Resources/config/services.xml — the DI wiring, mostly informative; you will not replicate this in Laravel.

First use case: a read-only, paginated, sortable index of one entity (User), rendered in Blade, backed by one Laravel endpoint that returns the jqGrid envelope from Eloquent. Get that end-to-end before touching search, filters, or inline editing — the envelope and the paging math are where the real decisions live.

Implementation Patterns

One grid definition per entity, kept out of the controller. Mirror the bundle's structure: a small class (or a config array / FormRequest-style object) per entity that declares columns, labels, formatters, and the query source. The controller stays thin — it resolves the definition, hands it the request, and returns JSON. This is the one architectural idea worth carrying over wholesale.

The endpoint is the real work. jqGrid sends page, rows, sidx, sord, _search, and optionally filters. Translate them onto an Eloquent builder, never onto hydrated results:

$perPage = (int) $request->input('rows', 20);
$page    = max(1, (int) $request->input('page', 1));
$sortCol = $request->input('sidx', 'id');
$sortDir = strtolower($request->input('sord', 'asc')) === 'desc' ? 'desc' : 'asc';

$query   = User::query();          // filters applied to the query, not the collection
$total   = (clone $query)->count(); // count BEFORE limit/offset
$rows    = $query->orderBy($sortCol, $sortDir)
                 ->forPage($page, $perPage)
                 ->get()
                 ->map(fn ($u) => ['id' => $u->id, 'cell' => [$u->id, $u->name, $u->email]]);

return response()->json([
    'page'    => $page,
    'total'   => (int) ceil($total / $perPage),
    'records' => $total,
    'rows'    => $rows,
]);

Whitelist every column name that arrives from the client. sidx and filters.rules[].field go straight into orderBy/where if you let them. Keep an explicit field → column map per grid definition and reject anything not on it — this is how you avoid SQL injection and unindexed full-table sorts at the same time.

Filtering via toolbar search. When _search=true, decode filters (it is a JSON string), then map each rules[] entry's field/op/data through the same whitelist:

if ($request->boolean('_search') && $raw = $request->input('filters')) {
    foreach (json_decode($raw, true)['rules'] ?? [] as $rule) {
        $column = $allowedColumns[$rule['field']] ?? null;
        if (!$column) continue;
        match ($rule['op']) {
            'eq' => $query->where($column, $rule['data']),
            'cn' => $query->where($column, 'like', '%'.$rule['data'].'%'),
            // ...only the operators you actually intend to support
            default => null,
        };
    }
}

Do not assume the bundle (or its reimplementation) sanitises operators or field names for you — treat it as your code.

Route + name indirection, carefully. The bundle-style pattern of a single generic dataAction that resolves a grid by a request-supplied name is convenient but dangerous. If you copy it, resolve only against a hardcoded allowlist (['users', 'orders']), never against an arbitrary container key.

Formatting belongs client-side wherever possible. Use jqGrid formatter/formatoptions (or your chosen table component's render hooks) for dates, badges, and action links. It keeps the PHP side serialisation-only and means the same endpoint can feed a different front-end later. Reserve server-side formatting for values that genuinely need logic the client cannot see (permissions, computed state).

Keep the front-end swappable. Because you own the envelope and the query translation, you can serve the same endpoint to jqGrid today and to TanStack Table / Livewire tomorrow. Write the controller as "produce this JSON shape from this builder," not as "produce jqGrid HTML."

Gotchas and Tips

  • It will not install cleanly on modern PHP/Laravel. Symfony 2-era require constraints conflict with PHP 8 and Laravel 10/11. --ignore-platform-reqs will download it and leave you with a runtime nothing bootstraps. Don't fight this — reimplement the contract instead.
  • Two EOL dependencies in one commit. Symfony 2 reached end-of-life in 2018; the open-source jqGrid line is effectively dormant (the actively developed line is the commercial Guriddo fork, which raises a licensing question). If you adopt jqGrid on the front end, a security scanner will flag it on every run — plan for that noise or don't adopt it.
  • total must come from the unpaged count. Deriving it from count($rows) makes the pager collapse to a single page the moment any filter is applied. Count the cloned query first, then apply limit/offset.
  • The bundle name doesn't match the repo name. The description calls it NeutronDataGridBundle, the repository is firano/datagrid-bundle. That usually signals a renamed fork or republished copy — verify provenance before trusting the code, and treat the MIT license as the only thing you can confirm.
  • jQuery must load before jqGrid. jqGrid is a jQuery plugin; if jQuery isn't on the page first, the grid silently no-ops with no console error you'll recognise as the cause. If jQuery is bundled, make sure it exposes window.jQuery, not a module-scoped instance.
  • Assets need manual wiring. The free jqGrid edition isn't cleanly distributed via npm, so Vite/esbuild will need manual copying or a direct asset reference alongside a pinned jQuery. This is awkward in a Laravel app and a good reason to pick a modern table component if you have the choice.
  • Deep OFFSET pagination degrades. jqGrid's page-number model forces offset-based paging, which is slow on large tables and blocks a keyset/cursor approach without fighting the client. Filter-heavy grids will need index review and query-plan testing regardless of how you implement it.
  • Inline editing and custom formatters are an XSS surface. Any HTML a formatter emits — server- or client-side — must be escaped. Audit any formatter returning raw HTML strings before shipping.
  • Debugging tips: log the incoming sidx/sord/filters verbatim, assert the resolved SQL with ->toSql() before running it, and diff your JSON envelope against the bundle's controller output field-by-field — the four envelope keys and the id/cell row shape are rigid, and a single missing key makes jqGrid render an empty grid without an obvious error.
  • Better options in the same slot: Filament or Livewire + Alpine for Laravel-native tables; yajra/laravel-datatables + DataTables if a mature jQuery-era grid is genuinely mandated; Inertia + a modern React/Vue table for client-side richness. Each has an active maintainer and current PHP support — which this package does not.
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.
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
noith/settings
kda/laravel-package