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

Admin Listing Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with 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.
  • No config publish is implied by this release; the only environment-level dependency is the database driver. On PostgreSQL, decide up front whether the unaccent extension will exist in every environment (local, CI, staging, production), because that single fact changes search semantics.
  • Also look at 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.
  • First use case: take an existing listing/filter endpoint, hand the raw user search string to 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.
  • If you maintain local infrastructure, reuse the shipped 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.

Implementation Patterns

  • Treat search as a service concern, not a query concern. Keep 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.
  • Pass an 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.
  • Stop defending against bad 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.
  • Numeric and date columns are safe to include in the searchable set on PostgreSQL. Since 2.1.0, adding an integer or 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.
  • Keep driver-specific configuration out of the service. The MariaDB 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.
  • Test against both drivers if you support both. The package's own CI now runs a PostgreSQL/MariaDB matrix with coverage reporting, so behaviour is contract-tested on both; mirror that in your app with a second CI job or a docker-compose profile using the new env-overridable connection settings.
  • Use the new tests as living documentation. 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.
  • Compose search with existing filters and pagination as before — the 2.1.0 release changed matching semantics only, not the filtering/pagination contract, and 2.2.0 changes only ordering defaults and error handling, so existing call sites should need no edits beyond verifying expectations around accents and invalid orderDirection values.

Gotchas and Tips

  • Accent-insensitivity is unconditional on MySQL/MariaDB. Any test asserting that Uložiť does not match Ulozit will fail after upgrading. Grep your test suite for diacritic fixtures before bumping the version.
  • On PostgreSQL, behaviour depends on an extension you may not control. With 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.
  • "Drop the extension for accent-sensitive search" is a database-wide decision. It affects every 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.
  • Invalid 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.
  • Default ordering is 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.
  • A null 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".
  • Expect index-usage changes. Wrapping columns in 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.
  • Debugging: dump the generated SQL via ->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.
  • CI flakiness: the docker-compose healthchecks are there for a reason. If you replaced the shipped compose file with your own, add equivalent waits, otherwise the new matrix-style dual-database runs will intermittently fail on connection refused rather than on real assertions.
  • Connection credentials and images changed in the package's own CI (both drivers connect as 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.
  • Dist archives are slimmer now. 2.2.0 adds .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.
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