---
title: "Caching, collections & pagination — Plausible for Laravel | Roundly"
description: "Cache any stats read by query signature, turn results into Collections, and walk every breakdown page with cursor() or each()."
url: https://roundly-consulting.com/open-source/docs/plausible-for-laravel/caching-pagination
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Plausible for Laravel](https://roundly-consulting.com/open-source/docs/plausible-for-laravel.md)

# Caching, collections & pagination

Cache any terminal call — aggregate(), timeseries(), breakdown(), run() or realtime() — by a deterministic signature of the query. Pass seconds or a DateTimeInterface, and optionally a cache store:

```php
$result = Plausible::stats()
    ->for('my-site.com')
    ->metrics(Metric::Visitors)
    ->cache(300)                       // seconds; or ->cache(now()->addHour(), 'redis')
    ->aggregate();

Plausible::stats()->for('my-site.com')->last7Days()->cache(now()->addHour(), 'redis')->timeseries();
Plausible::stats()->for('my-site.com')->cache(30)->realtime();
```

The key is plausible:stats: plus a hash of the whole query — type, site, metrics, filters, dimensions, ordering, includes, period, interval, dates, comparison, property and page — so different queries never share an entry. The decoded response is cached and the typed result is rebuilt on each hit.

## Collections

Every result exposes collect() for an Illuminate\\Support\\Collection of typed rows; aggregate() returns a metric-keyed collection of values:

```php
use RoundlyConsulting\Plausible\Enums\Property;

Plausible::stats()->for('my-site.com')->breakdown(Property::VisitSource)->collect(); // Collection<int, BreakdownRow>
Plausible::stats()->for('my-site.com')->timeseries()->collect();                    // Collection<int, TimeseriesPoint>
Plausible::stats()->for('my-site.com')->aggregate()->collect();                     // ['visitors' => 2001, ...]
```

## Auto-paginating breakdowns

cursor() and each() transparently walk every page of a breakdown using PHP generators, so you never write a page loop. Pages are fetched on demand, so large breakdowns never load at once:

```php
use RoundlyConsulting\Plausible\Enums\Property;
use RoundlyConsulting\Plausible\Results\BreakdownRow;

foreach (Plausible::stats()->for('my-site.com')->cursor(Property::VisitSource) as $row) {
    // every row across every page
}

Plausible::stats()->for('my-site.com')->each(function (BreakdownRow $row) {
    // return false to stop early
}, Property::VisitSource);
```

The walk starts at page 1 and stops at the first page with fewer rows than perPage(). Raise perPage() to walk the same breakdown in fewer, larger requests. When the walk ends or stops early, the builder’s own page() is restored, so a later breakdown() on the same builder fetches its page again. Without a property, cursor() and each() throw MissingConfiguration.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/plausible-for-laravel.md)
