Example reports

Every feature of the package lands in a running example. Open the preview, read the code, then adapt it.

Price list · Grouped list with subtotals

Groups Aggregates Filters Flow /reports/price_list/run

A report start band with the title, a grid header, a detail band, one group per category with its own header and footer, a summed subtotal, a report end band and a filter form.

  • A reportStart() band for the title and a reportEnd() band for the summary — once per report
  • A grid header, then a detail band rendered once per record
  • A group per category with its own header and footer bands
  • A subtotal per group via aggSum()
  • A filter form with typed controls (text, enum, number, relation)

Packing list · Strict placement

Strict Pagination /reports/packing_list/run

Fixed-height bands placed arithmetically across pages, with a repeated grid header and page numbers.

  • Strict mode: fixed band heights and arithmetic pagination
  • A repeated grid header on every page
  • Page numbers in the page footer
  • 60 demo positions, so the report spans several pages

Label sheet · N-up detail band

Strict N-up /reports/label_sheet/run

One full-width detail band split into four cells per row: 30 labels across two pages, with the row as the unit of pagination.

  • One detail band, four cells per row via columns(4, gap: 3, rowGap: 2)
  • gap spaces the cells horizontally, rowGap the rows vertically
  • Detail::height is the height of the row, not of a single label
  • The engine wraps every row in its own grid — never one grid across pages
  • The last row is padded with empty cells so the columns stay aligned
  • Strict mode: 7 rows × 4 labels = 28 labels per page, with page numbers in the footer

Invoice · Free-form form with payment slip

Strict Free-form Pagination /reports/invoice_example/run

One complete invoice per record, built from page blocks with declared heights. The Swiss QR payment slip stays on page 1 when it fits and moves to page 2 when the invoice positions need the space.

  • freeform() renders one complete form per detail record
  • Every section is an <x-reports::page-block> with a declared height
  • The payment slip is anchored with anchor="bottom": 105 mm from the paper edge, overlaying the footer
  • pageNumbering(perForm) restarts the page counter for every invoice
  • The page header with invoice number and customer is hidden on page 1
  • A block taller than the page body throws a BandOverflowException

Car purchase contract · Free-form flow with general terms

Flow Free-form /reports/contract_example/run

A car purchase contract in Flow mode. The browser paginates the prose, and a CSS page break starts the general terms on page 2.

  • freeform() in Flow mode: no fixed page blocks, just Blade markup
  • The general terms start on page 2 via break-before: page
  • Long clauses flow naturally across page boundaries
  • break-inside: avoid keeps individual clauses together
  • pdfFooter() adds a PDF-only footer with pageNumber/totalPages
  • The same contract can be exported as HTML preview and PDF

Data sources · SQLite-backed source adapters

Flow Filters Aggregates /reports/database_sources/run

One report, five source adapters: QuerySource, EloquentSource, RawSqlSource, CollectionSource and ArraySource all read the same SQLite table. Pick the adapter in the filter form.

  • A real SQLite table with demo orders, created by a migration
  • QuerySource and EloquentSource push filters and sorting into SQL
  • RawSqlSource, CollectionSource and ArraySource filter and sort in memory
  • The source selector is a normal typed filter control
  • Report start/end bands show the active adapter and the aggregated totals

Multilingual price list · Pick language and format in the frame header

Flow Language Aggregates /reports/multilanguage/run

Switch the language directly in the preview header. Report texts come from the module lang directory; dates and numbers follow the format locale, while the currency stays CHF.

  • Language selection in the report frame header
  • Module translations under app/Reports/Multilanguage/lang
  • Product, category and status texts come from language arrays in the source (like Spatie Translatable)
  • Dates and numbers follow the format locale (de_CH vs. en_US)
  • The currency stays CHF independently of the language
  • The switch applies to HTML preview and PDF

Grouped revenue with enrichment · Group data from an Eloquent model

Flow Groups Language Aggregates Enrichment /reports/group_enrichment/run

The detail rows come from demo_orders. Every group header loads its translated category name and target through enrichWith() from the demo_categories Eloquent model.

  • enrichWith() runs once per group, not per detail row
  • The group keys are passed to the enrichment source as filters
  • Eloquent returns the translated attribute because the engine set app()->getLocale()
  • The group data is available as $ctx->groupData() in header and footer bands
  • Group aggregate via $r->aggregate(..., scope: "group:1")
  • The language switch in the frame header affects category names and number formatting