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

Report Bundle Laravel Package

pitoune/report-bundle

pitoune/report-bundle is a reporting package for PHP applications that helps you define report structures, generate report output, and add reusable reporting features to your project with minimal setup. It is suited for dashboards, admin panels, and scheduled report workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the framing. pitoune/report-bundle is not a Laravel package. It is a read-only subtree split of Sylius/Bundle/ReportBundle from the Sylius e-commerce platform (Symfony). It contains the Report / ReportData entities, the report admin controller, form types, the data-fetcher and renderer registries, and the built-in fetchers/renderers. "Leveraging it day-to-day" realistically means one of two things:

  1. You are on Sylius and want to build custom reports on top of the in-tree bundle (the split is a convenience mirror, not something you should install standalone).
  2. You are on Laravel and are looking at this as a reporting system — in which case you should read it as a design reference and not as a dependency.

Minimal steps for the Sylius case:

# The split lags the platform. Use the bundle that ships with Sylius instead.
composer require sylius/sylius
// config/bundles.php
return [
    // ...
    Sylius\Bundle\ReportBundle\SyliusReportBundle::class => ['all' => true],
];

If you want the split specifically, check the live constraint on Packagist rather than trusting the old ^0.18 pin — the project is now tagging 1.0.0-beta.* releases (current: v1.0.0-beta.2.1). A 1.0.0-beta tag is still a beta: it does not promise a stable API, and it does not by itself prove the Symfony/PHP floor has moved. Read the composer.json of the tag before requiring it:

composer require pitoune/report-bundle:^1.0@beta

Where to look first: the parent repository, Sylius/Sylius, under src/Sylius/Bundle/ReportBundle, plus its Model/, Entity/, and DependencyInjection/Compiler/ directories (the registry wiring is the part that actually matters). The Sylius docs page on reports describes the admin workflow.

First use case: create a report through the Sylius admin (/admin/reports) using the built-in data fetcher and table renderer, then open it. That gives you the full loop — Report config → fetcher → ReportData → renderer → HTML. Once that works, replace the fetcher with your own metric (sales by channel, stock turnover, refund rate). That custom fetcher is where 90% of real work lives. If your metric naturally produces a nested shape (channel → month → row), the renderer can now display it as-is (see below) instead of you flattening it first.

Implementation Patterns

The report is configuration, not code. A Report row carries code, name, dataFetcher, renderer, and dataFetcherConfiguration (a form payload serialized into the entity). Reports are therefore data-driven: the admin form builds the configuration array, and the fetcher interprets it at render time.

Custom data fetcher — the core extension point:

use Sylius\Bundle\ReportBundle\Model\ReportInterface;
use Sylius\Bundle\ReportBundle\Model\ReportDataInterface;
use Sylius\Bundle\ReportBundle\DataFetcher\DataFetcherInterface;

final class RefundRateDataFetcher implements DataFetcherInterface
{
    public function fetch(ReportInterface $report, array $configuration = []): ReportDataInterface
    {
        $from = $configuration['startDate'] ?? (new \DateTime('-30 days'))->format('Y-m-d');
        $to   = $configuration['endDate']   ?? (new \DateTime())->format('Y-m-d');

        // Build rows from your repository; return a ReportData populated with
        // data + labels, which the renderer consumes.
    }
}
# services.yaml
App\Report\RefundRateDataFetcher:
    tags: ['sylius.report_data_fetcher']

Nested data is now a first-class shape. v1.0.0-beta.2.1 adds rendering of multidimensional arrays. Practical consequence: your fetcher can return grouped data — e.g. ['Web' => ['2024-01' => [...], '2024-02' => [...]], 'Retail' => [...]] — and the table renderer will present it without you pre-flattening. Two rules still apply:

  • Pre-flatten for anything machine-readable. CSV/Excel exports, API payloads, and chart series usually want a flat [row] shape. Keep a flatten() step (or a second, flat rendering path) for those consumers; the renderer's nested display is a presentation concern, not a data contract.
  • Decide the shape in the fetcher, not the template. Because the array is persisted-adjacent (it is regenerated every render, but consumers depend on its shape), keep grouping deterministic and key-stable. Sorting nested keys in the fetcher beats fixing it downstream.

Custom renderer — implement RendererInterface (render(ReportDataInterface $data): string) and tag it sylius.report_renderer. The bundle ships table and chart renderers; both emit HTML fragments, so add your own escaping if any label/column comes from user-controlled data. If you write your own renderer, handle nested arrays recursively or explicitly flatten on entry — the built-in renderer's new behaviour is not automatically inherited by custom implementations.

Admin form extension. Add the configuration fields your fetcher expects by extending the report form type from ReportType::class (or overriding the template that builds the fetcher-specific panel). Keep the resulting array shape stable — it is persisted.

Fetching outside the admin. For dashboards, cron exports, or API endpoints, resolve the fetcher and call it directly:

$report = $reportRepository->findOneBy(['code' => 'refund_rate']);
$data   = $dataFetcherRegistry
    ->get($report->getDataFetcher())
    ->fetch($report, $report->getDataFetcherConfiguration());

Note that fetch() is synchronous and does no caching. For anything scheduled, wrap it in a console command, cache the resulting ReportData (or its CSV/JSON serialization), and stamp a generatedAt. Don't let a heavy aggregate query sit behind a page render.

Laravel integration. If the reporting need is Laravel-side, don't bridge the bundle — the container, Doctrine mappings, and admin assumptions don't translate. Instead use it as a spec: separate "data fetcher" and "renderer" concerns, persist report definitions as rows with a config column, and implement each metric as a query object plus a Blade/API presenter. That is what the bundle is doing, minus the Symfony baggage. Pair with maatwebsite/excel for exports and a scheduled command for materialization.

Gotchas and Tips

  • Maintenance status is unclear, not dead. The project had been dormant since 2017 and is now shipping 1.0.0-beta.* tags; the latest (v1.0.0-beta.2.1) is a one-line change ("display multidimensional arrays"). Beta numbering plus a single terse note means: read the diff, don't assume a maintained platform. Still treat it as reference source, not a drop-in dependency.
  • The subtree split is READ-ONLY. Issues and pull requests go to Sylius/Sylius. Filing against this repo does nothing — including reporting bugs in the new nested-array rendering.
  • Version constraints will bite. Verify the tag's composer.json: a 1.0.0-beta version number does not guarantee Symfony 5+/PHP 8. If it still resolves Symfony 2.8/3.x and Doctrine ORM 2.x, installing it in a PHP 8 / Laravel 10+ app will fail resolution or fatal on signatures (DataFetcherInterface, return types, deprecated Doctrine APIs).
  • Service tags are compile-time. Adding sylius.report_data_fetcher or sylius.report_renderer requires a cache clear/container rebuild. If your fetcher "doesn't exist" in the registry, this is almost always why.
  • dataFetcherConfiguration is opaque and persisted. There is no migration story for it. Changing the admin form shape silently breaks previously saved reports; version your configuration keys and validate them defensively in fetch().
  • Multidimensional arrays are a display feature, not a data model. The new rendering path changes how nested ReportData looks, not how it is stored or exported. Anything that serializes ReportData (CSV, JSON API, chart JS) must be checked after upgrading — nested rows can silently become Array strings in naive exporters.
  • Deep nesting has no depth guard you should rely on. Recursive label/row rendering on a user-shaped array is a plausible way to blow up the page; cap your grouping depth (two levels is usually enough for a report table) and flatten or paginate beyond that.
  • Doctrine mapping overrides. The bundle's entities are mapped via XML; override with doctrine.orm.resolve_target_entities or attribute overrides rather than editing vendor code, since you cannot patch a subtree split.
  • Synchronous, uncached fetches. Admin report views execute the fetcher on every request. Add your own caching layer before pointing a dashboard at it.
  • Rendering is HTML-in-PHP. Renderers return strings; if a chart library is injected, it comes from the bundle's template. Escape labels and series names yourself — nested group headers are still user-influenced strings.
  • Modern alternatives. On Sylius, use the in-tree SyliusReportBundle from the matching Sylius release rather than this split. On Laravel, build the fetcher/renderer split yourself with query objects, maatwebsite/excel for exports, and a scheduled command to precompute aggregates — you will get a maintained, testable version of the same pattern with a fraction of the integration risk.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core