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

Eloquent Report Generator Laravel Package

langleyfoxall/eloquent-report-generator

Generate reports directly from your Laravel Eloquent models. Define columns and queries declaratively, then export results as tables or downloadable files with minimal boilerplate and clean, readable code.

View on GitHub
Deep Wiki
Context7

Getting Started

The package turns an Eloquent query into a tabular report — you describe the model, the columns, and the query, and it handles rendering, column formatting, and (depending on config) export.

v1.1.0 is the release to start on, but note the version jump: the previous tag was v0.2.0, so v1.0.0 happened somewhere in between and almost certainly carried breaking changes. The changelog diff to read is compare/v0.2.0...v1.1.0, and PR #5 ("Upgrade") is the only listed change — read that PR before copying any snippet from an old blog post or the 0.x README, because pre-1.0 examples are the most likely thing to be stale.

Minimal steps:

  1. composer require langleyfoxall/eloquent-report-generator:"^1.1" — use a caret constraint, not dev-master, so you actually get the 1.x API.
  2. Look first at src/ for the base report class and the column/field definition objects, then the package's own tests — with a thin changelog, the test suite is the most reliable documentation of the current API surface.
  3. Publish any config/views with php artisan vendor:publish --provider="LangleyFoxall\..." if the service provider offers them (check config/ in the package).
  4. First use case: a read-only admin report. Pick a query you already trust — e.g. Order::query()->with('customer') — define the columns, and render it at a single route behind your existing auth middleware. Resist wiring it into exports or scheduled output until you've confirmed the 1.x API holds up in your app.

Implementation Patterns

Report class per report. The idiomatic shape is one class per report, holding three concerns in one place: the base query, the column definitions, and any per-column formatting. Keep the query as a Builder (return Order::query(), not ->get()), so the package can still apply its own sorting, pagination, or chunking on top. If you return a hydrated collection you lose all of that.

Scope the query, don't filter after. Authorization belongs inside the base query — ->where('tenant_id', auth()->user()->tenant_id) — so every consumer of the report (view, export, queued job) inherits the restriction. Filtering in the view or in a post-query step is how reports leak other tenants' rows.

Eager-load aggressively. Columns that reach through a relation ($order->customer->name) are the number-one source of N+1 in report code, because a report renders every row. Add ->with([...]) for every dotted/relation column at definition time, and add Model::preventLazyLoading() in local/CI so a missed with() fails loudly instead of quietly issuing 500 queries.

Format at the column, not in the view. Keep money/date/enum formatting attached to the column definition so the Blade view, CSV export, and any JSON output all agree. If you find yourself writing number_format() in a template, that formatting belongs on the column.

Chunk for large reports. Anything that can exceed a few thousand rows should go through chunkById()/lazy() or the package's own pagination rather than a single ->get(). If you add a queued export, use chunkById (not chunk) — it's stable against rows being inserted or deleted mid-run, which matters on live tables.

Wrap in a route + policy, not a controller action. Reports are essentially a second read path into your data, so give them the same treatment as any other endpoint: a policy check, a named route, and a feature test asserting that user A cannot see user B's rows. That test is cheap and catches the scoping mistakes above.

Test against SQLite in memory. Reports are pure query + formatting, so a handful of factories and an assertion on the rendered output covers most of the risk without touching your real database.

Gotchas and Tips

  • The 0.x → 1.x jump is the main risk. Release notes list only "Upgrade" (PR #5). Treat the 1.x API as new: if you have any existing 0.2.0 integration, don't bump the constraint and hope — read the diff, run the suite, and check specifically for renamed methods, changed constructor/method signatures on the report base class, and changed column-definition argument order.
  • Pin the version in composer.json ("^1.1") and commit the lock file. With no detailed changelog, an accidental minor bump is an unnecessary gamble on a package that just made a major version leap with a one-line release note.
  • Check whether config/views need re-publishing after the upgrade. Packages that ship Blade views frequently change them between majors, and a stale published view will silently override the new one — a classic "I upgraded and nothing changed" bug. php artisan vendor:publish --force for the views only, and diff before committing.
  • Raw SQL in column definitions is an injection and portability hazard. If a column accepts a raw expression, never interpolate user input into it; and remember raw expressions that work on MySQL may not on SQLite/Postgres, which will only bite you in CI or on a read replica.
  • Debug by dumping the SQL. When a report is empty or slow, log $query->toSql() with ->getBindings() before handing it to the package. Most "the report is broken" issues are a where that filtered everything out, not a rendering bug.
  • Timezone and null formatting. Dates typically come back as Carbon in app timezone while your DB stores UTC, and nulls in a formatted column often render as an empty string rather than —. Decide both conventions once, at the column level, rather than per report.
  • Extension points to look for before forking the package: a custom column/field type (for a badge, link, or progress bar), an overridable render/export method on the base report class, and any registered Blade namespace. If the base class exposes these, subclass it once as an App\Reports\BaseReport and put your house style (date format, money format, empty-value placeholder, tenant scoping) there — that single indirection makes the next major upgrade far cheaper.
  • Don't rely on it for heavy analytics. This is a query-then-render tool, not an aggregation engine. Anything needing multi-table rollups or window functions belongs in a dedicated query/view or a reporting table, with this package rendering the result.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin