dejwcake/admin-listing
A Laravel package for building admin data listings with configurable columns, filters, search, and row actions. It helps developers scaffold management screens and searchable tables quickly while retaining control over queries, views, and authorization.
composer require the package (pin ^2.2 to pick up both the 2.1.0 accent-insensitive search and the 2.2.0 ordering improvements), then check the README section covering ListingService — that class is the entry point for all search behaviour described in 2.1.0.unaccent extension will exist in every environment (local, CI, staging, production), because that single fact changes search semantics.ListingQueryBuilder::fromRequest() and the new Brackets\AdminListing\Enums\OrderDirection enum — as of 2.2.0 the builder accepts an optional $defaultOrderDirection, so ordering is now an explicit decision at the call site rather than an implicit Asc.ListingService, and hit it with a diacritic query (Uložiť) and its ASCII twin (Ulozit). Both should return the same rows on MySQL/MariaDB out of the box, and on PostgreSQL once unaccent is installed. Then request ?orderDirection=desc and ?orderDirection=garbage and confirm both give you sane, non-500 results.docker-compose.yml — 2.1.0 added database healthchecks there, and 2.2.0 moved the MariaDB image to 12.3, so a fresh docker compose up matches what the package tests against.ListingService as the single place a search term is interpreted; controllers and form requests should pass a raw string and never pre-normalise case or strip accents themselves. Double-normalisation makes behaviour harder to reason about when the driver-level rules change again.OrderDirection enum, not a string. fromRequest() now takes an optional OrderDirection $defaultOrderDirection (default OrderDirection::Asc). Pick the default per listing at the call site — Desc for "newest first" feeds, Asc for alphabetical pickers — rather than relying on the package default everywhere. Use the enum in your own code too, so a future enum case change is a static-analysis error rather than a silent runtime fallback.orderDirection. 2.2.0 makes an invalid or non-string orderDirection fall back to the default instead of throwing. Delete any try/catch you wrapped around fromRequest() for that reason, and if you do want a 422 for bogus input, validate it in a FormRequest using the enum's values — the builder will no longer be your validation layer.searchIn may now be null. ListingService no longer fails when ListingQuery::$searchIn is null, which makes dynamically-assembled searchable column sets (feature flags, tenant-specific schemas, permission-scoped columns) safe to pass through. Make sure a null set is intended — the search term is then simply not applied, and the listing degrades to an unfiltered browse instead of erroring.date column to the searchable columns list no longer produces No function matches the given name and argument types; the new CAST(... AS TEXT) removes that. You can let one search box span titles, codes, prices and dates without per-driver column lists.CONVERT(... USING utf8mb4) COLLATE utf8mb4_unicode_ci and the PostgreSQL unaccent()/ILIKE branches are selected internally. Don't branch on DB::connection()->getDriverName() in your own code to mirror it — you'll drift from the package.AttachSearch and NonTextColumnSearch in the package's suite demonstrate the supported shapes (search combined with attached relations, search across non-text columns). Read those before writing your own integration tests rather than inferring behaviour from the README alone.orderDirection values.Uložiť does not match Ulozit will fail after upgrading. Grep your test suite for diacritic fixtures before bumping the version.unaccent installed you get accent-insensitive matching; without it you silently fall back to plain ILIKE (case-insensitive, accent-sensitive). Local dev with the extension and production without it produces a class of bug that only shows up with real user data — verify SELECT * FROM pg_extension WHERE extname = 'unaccent' per environment.unaccent() usage in the schema, not just this package, and it may need superuser privileges to reverse. Don't reach for it casually as a per-feature toggle; if you genuinely need both behaviours, that's an argument for an application-level normalised search column rather than flipping extensions.orderDirection is now silent. A typo'd ?orderDirection=descc or an array-shaped orderDirection[] no longer throws — it quietly orders Asc. That's friendlier for end users and worse for debugging: a bug in your frontend's sort control now manifests as "sorting doesn't work" with no exception and no log line. Validate explicitly where ordering is a user-visible contract, and add a test asserting your fallback choice.Asc if you don't set one. If you have listings where "no explicit sort" previously meant something else (or where you sorted in PHP afterwards), 2.2.0 makes the package's intent explicit. Audit any call to fromRequest() that omits the argument.searchIn is a silent no-op. The fix removes a crash, but a null that arrives because your column-resolution logic failed will now produce an unfiltered listing rather than an error page. Assert in tests that a search term actually narrows results, so a null regression can't hide behind "the page still renders".CONVERT(...)/unaccent()/CAST(... AS TEXT) generally prevents plain B-tree indexes on those columns from being used for the match. On large tables, consider a generated/stored normalised column with its own index, or measure before assuming the new query plan is acceptable.CAST(... AS TEXT) changes comparison semantics for non-text columns. Searching 2024 now matches a date or numeric column as a string; be aware that formatted output can vary (2024-01-01 vs locale/format differences) and that numeric-looking search terms will now match far more rows than before. Scope searchable columns deliberately.->toSql() / DB::listen() to confirm which branch ran — the presence or absence of unaccent( is the fastest way to tell whether your PostgreSQL environment is behaving as expected. The order by clause in the same dump tells you whether your OrderDirection default was applied or the request value won.laravel, MariaDB image is now 12.3). Irrelevant to consumers unless you copied the package's CI config — if you did, port the env-overridable settings rather than hardcoding again..gitattributes to keep dev files out of dist. If you vendor-copy files from the package (rather than installing via Composer), don't assume the package's own tests, docker-compose or AGENTS.md/CLAUDE.md are present in what you pull.AGENTS.md / CLAUDE.md shipped for AI-assisted work. Useful as an extension-point map if you contribute upstream or want a model to follow package conventions; not consumed by your application at runtime.How can I help you explore Laravel packages today?