mistralys / application-datagrids
PHP classes to abstract the rendering of HTML tables.
Package info
github.com/Mistralys/application-datagrids
pkg:composer/mistralys/application-datagrids
Requires
- php: >=8.4
- mistralys/application-utils-core: >=2.5.0
- twbs/bootstrap: ^5.3.3
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpstan/phpstan-phpunit: ^2.0
- phpunit/phpunit: ^12.0
- roave/security-advisories: dev-latest
This package is auto-updated.
Last update: 2026-03-14 21:43:19 UTC
README
PHP classes to abstract the rendering of HTML tables, with switchable renderers and a straightforward fluid and chainable API.
NOTE: Work in progress, but the examples work already.
Requirements
- PHP 8.4 or higher
- Composer
- Webserver
Viewing the examples
- Clone the repository.
- Run
composer installto install the dependencies. - Open the
examplesfolder through your webserver.
Each example uses a shared JsonFileStorage instance (created in examples/bootstrap.php) to persist per-grid settings. The examples/storage/ directory is created automatically on first use — no manual setup is required.
Usage
Creating a grid
Every DataGrid instance requires a string ID (strict kebab-case: ^[a-z][a-z0-9]*(-[a-z0-9]+)*$) and a storage handler that implements GridStorageInterface. The library ships a file-backed implementation, JsonFileStorage:
use AppUtils\Grids\DataGrid; use AppUtils\Grids\Storage\Types\JsonFileStorage; $storage = new JsonFileStorage('/path/to/storage/dir'); $grid = DataGrid::create('my-grid', $storage); $grid->columns()->add('name', 'Name'); $grid->columns()->add('status', 'Status'); $grid->rows()->addArray(['name' => 'Alice', 'status' => 'Active']); $grid->rows()->addArray(['name' => 'Bob', 'status' => 'Inactive']); echo $grid;
The JsonFileStorage constructor creates the storage directory if it does not exist. One JsonFileStorage instance can be shared across all grids on a page; data is keyed by grid ID internally.
Per-grid settings (items per page)
Use $grid->settings() to read and write typed per-grid settings persisted via the storage handler. The first available setting is items per page for pagination:
// Read the stored value, falling back to 25 if nothing is persisted yet: $itemsPerPage = $grid->settings()->getItemsPerPage(25); // Build the pagination provider with the effective value: $provider = new \AppUtils\Grids\Pagination\Types\ArrayPagination($allItems, $itemsPerPage); $grid->pagination()->setProvider($provider); $grid->rows()->addArrays($provider->getSlicedItems()); // Persist an updated preference (e.g. after a user submits a preference form): $grid->settings()->setItemsPerPage(50);
Settings are stored per grid ID, so multiple grids on the same page are fully isolated. To use a custom storage backend (database, session, Redis, etc.), implement the two-method GridStorageInterface:
use AppUtils\Grids\Storage\GridStorageInterface; class SessionStorage implements GridStorageInterface { public function get(string $gridID, string $key, mixed $default = null): mixed { return $_SESSION['grids'][$gridID][$key] ?? $default; } public function set(string $gridID, string $key, mixed $value): void { $_SESSION['grids'][$gridID][$key] = $value; } }
Built-in items-per-page selector
Call setItemsPerPageOptions() on the grid's pagination instance to enable an automatic dropdown
selector rendered as part of the pagination row — no separate form or handler required:
use AppUtils\Grids\Pagination\Types\ArrayPagination; $pagination = $grid->pagination(); // Define the available choices: $pagination->setItemsPerPageOptions([10, 25, 50, 100]); // Resolve the effective value — priority: $_GET['ipp'] → persisted setting → default: $itemsPerPage = $pagination->resolveItemsPerPage(25); // Build the provider with the resolved value: $provider = new ArrayPagination($allItems, $itemsPerPage); $pagination->setProvider($provider); $grid->rows()->addArrays($provider->getSlicedItems()); echo $grid; // selector appears automatically next to the page-jump input
The selected value is persisted via GridSettings so it survives across page loads. When the
user picks a new value, $_GET['ipp'] is detected on the next request, validated against the
configured options whitelist, persisted, and used for the current render.
Backward compatibility: grids that do not call setItemsPerPageOptions() are unaffected —
the pagination row continues to be hidden on single-page results exactly as before.
Visibility rule: when at least one IPP option is configured, the pagination row is shown even
when totalPages <= 1 (e.g. a zero-row grid), so users can always change the page size.
Bootstrap 5 renderer: the <select> is automatically wrapped in a
d-flex align-items-center gap-2 mt-2 container and styled with form-select form-select-sm.
GET parameter name: defaults to ipp. Change it with $pagination->setItemsPerPageParam('per_page')
if it conflicts with another parameter on the same page.