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

Laravel Report Generator Laravel Package

jimmyjs/laravel-report-generator

Quickly generate PDF, Excel, and CSV reports in Laravel from any query builder or Eloquent query. Define columns, grouping, and aggregates in PHP, render with Blade views, and export or stream polished reports through a simple, fluent API.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the wrapper and its drivers. The package itself is thin — it orchestrates barryvdh/laravel-dompdf (or laravel-snappy) and maatwebsite/excel, so you need to install the driver you intend to use, then the package:

composer require barryvdh/laravel-dompdf maatwebsite/excel
composer require jimmyjs/laravel-report-generator

The service provider is auto-discovered. Publish the config (and views if you plan to restyle PDFs):

php artisan vendor:publish --tag=report-config

Where to look first. Read config/report-generator.php to see the default PDF/Excel settings (paper size, orientation, view templates), then skim src/ReportGenerator.php — the whole public surface is essentially of(), editColumn(), setMeta(), showHeader(), download(), show(). The package is small enough to fully understand in ~20 minutes.

First use case. The canonical day-one report is an admin "export filtered list" button. Build your query in the controller, define a header→column map, and hand it off:

use Jimmyjs\ReportGenerator\Facades\ReportGenerator;

public function users()
{
    $query = User::query()->latest();

    $columns = [
        'Name'       => 'name',
        'Email'      => 'email',
        'Created At' => 'created_at',
    ];

    return ReportGenerator::PdfReport()
        ->of('User Report', $columns, $query)
        ->showHeader()
        ->download('users-' . now()->format('Y-m-d'));
}

Swap PdfReport() for ExcelReport() and the same query/columns produce a spreadsheet. That symmetry is the core value proposition — you write the query and column map once.

Implementation Patterns

One query, two media. The highest-leverage pattern is a private method returning [$columns, $query], then two thin controller actions (exportPdf, exportExcel) that differ only in the media call. This keeps filter logic in one place and prevents PDF/Excel drift. Pass the same request filters into the query builder:

private function userQuery(Request $request)
{
    return User::query()
        ->when($request->role, fn ($q, $r) => $q->where('role', $r))
        ->when($request->from, fn ($q, $d) => $q->whereDate('created_at', '>=', $d));
}

Column maps do the heavy lifting. Keys are the human-readable headers, values are the model attribute or accessor. For anything that isn't a plain string, reach for editColumn() with a closure — this is where you format dates, currency, booleans, and relations:

->editColumn('created_at', fn ($row) => $row->created_at->format('d M Y'))
->editColumn('status', fn ($row) => ucfirst($row->status))

Meta describes the report, not the data. Use setMeta() to inject the filter set (date range, role, generated-by) into the report header so the PDF is self-explanatory when someone forwards it. This is what turns a data dump into a report stakeholders trust.

Header/footer and orientation are per-report. showHeader() / setOrientation('landscape') / setPaper('a4') are chainable, so wide tables (many columns) get landscape while summary reports stay portrait. Configure the PDF view template once in the published config, not per call.

Encapsulate reusable reports. For anything used more than twice, extract a small report class per domain (e.g. App\Reports\UserReport) with a build(Request $request): array returning query+columns. Controllers stay thin and the report becomes unit-testable.

Queue large exports. For anything above a few thousand rows, generate in a job, Storage::put() the file, and email or notify the user with a signed download URL. Synchronous PDF generation in a request is the #1 cause of timeouts with this package.

Gotchas and Tips

DomPDF is the bottleneck, not the package. Rendering 5k+ rows as HTML into PDF will blow memory or hit max_execution_time. Keep PDF reports summarised (aggregates, top-N, paginated sections) and push full exports to Excel. Raise memory_limit cautiously; chunk your query rather than the PDF render.

Pin your Excel version. The package was built against maatwebsite/excel 3.x. If you're on a newer Laravel with a different Excel major, install the driver version the package declares in composer.json first, or the export will fail at runtime with a class-not-found in the writer pipeline.

Carbon and enums don't auto-format. Raw created_at values will render as 2024-01-15T00:00:00.000000Z in the PDF. Always editColumn date columns. Same for enums — cast them to ->value or a label accessor.

select() breaks eager-loaded accessors. If your column map references $row->relation->name, use with('relation') and avoid restrictive select() calls that drop the foreign key. SQLite/MySQL will silently return null and your PDF will look empty.

Filename sanitisation is on you. download($name) passes through to the response header; strip slashes, colons, and non-ASCII from user-supplied names or downloads fail on Windows clients.

Publish views before customising. Overriding the PDF Blade template without publishing gives you a confusing "view not found" — publish with vendor:publish --tag=report-views (check the exact tag in the README) and edit in resources/views/vendor/.

Version risk. Last release was April 2022 and it targets Laravel 5-era APIs. On Laravel 10/11, test the facade binding and the dompdf/excel dependency resolution before committing — if it fights Composer, either pin to a compatible Laravel or vendor the ~200 lines of orchestration into your own App\Support\Reports layer. The package is simple enough to fork; treat it as a reference implementation as much as a dependency.

Testing tip. Assert on Content-Type (application/pdf, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) and Content-Disposition rather than parsing the binary. For content assertions, test the query/column-map builder method directly — that's where the logic lives.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib