andrewdyer/metrics
Composer 安装命令:
composer require andrewdyer/metrics
包简介
A metrics library for Eloquent applications that calculates strongly typed aggregates over a configurable date range
README 文档
README
A metrics library for Eloquent applications that calculates strongly typed aggregates over a configurable date range.
Introduction
This library provides Eloquent-based metric calculations, returning strongly typed result objects for scalar aggregates, time-grouped trends with zero-filled gaps, and categorical breakdowns, all with JSON serialisation support. It works in any PHP application with an Eloquent connection, including outside Laravel via the Capsule manager.
Prerequisites
- PHP: Version 8.3 or higher is required.
- Composer: Dependency management tool for PHP.
- Eloquent ORM: An configured Eloquent connection is required.
Installation
composer require andrewdyer/metrics
Getting Started
1. Set up Eloquent
This library requires an Eloquent connection. In a Laravel application this is configured automatically. Outside of Laravel, bootstrap Eloquent using the Capsule manager:
use Illuminate\Database\Capsule\Manager as Capsule; $capsule = new Capsule(); $capsule->addConnection([ 'driver' => 'mysql', 'host' => '127.0.0.1', 'database' => 'my_database', 'username' => 'root', 'password' => '', 'charset' => 'utf8', 'prefix' => '', ]); $capsule->setAsGlobal(); $capsule->bootEloquent();
2. Create a metric
Extend Value and implement calculate() to define the query, and getStartDate() / getEndDate() to define the date range:
use AndrewDyer\Metrics\Value; use AndrewDyer\Metrics\Results\ValueResult; use DateTimeImmutable; class TotalNewUsers extends Value { public function calculate(): ValueResult { return $this->count(User::query()); } public function getStartDate(): DateTimeImmutable { return new DateTimeImmutable('first day of this month'); } public function getEndDate(): DateTimeImmutable { return new DateTimeImmutable('last day of this month'); } }
Usage
Calculating a metric
Call calculate() on any metric instance to run the query and return a typed result:
$metric = new TotalNewUsers(); $result = $metric->calculate(); $result->getResult(); // e.g. 42
JSON serialisation
All result objects implement JsonSerializable:
json_encode($metric->calculate()); // {"result": 42}
Customising the metric name and description
Override getName() and getDescription() on any metric to provide a human-readable label:
public function getName(): string { return 'Total New Users'; } public function getDescription(): string { return 'The total number of users who signed up this month.'; }
Rounding
Override getRoundingPrecision() and getRoundingMode() to control how aggregate values are rounded:
public function getRoundingPrecision(): int { return 2; } public function getRoundingMode(): int { return PHP_ROUND_HALF_UP; }
Metric Types
Value
A Value metric calculates a single aggregate over a date range. When the model uses timestamps, the date filter defaults to created_at. When the model does not use timestamps, no date filter is applied unless an explicit $dateColumn is passed.
Count
Returns the number of records within the date range:
$this->count(User::query());
To filter by a specific date column, pass it explicitly:
$this->count(User::query(), null, 'published_at');
On models without timestamps, no date filter is applied unless an explicit column is given:
$this->count(Product::query()); // no date filter — all records returned $this->count(Product::query(), null, 'released_at'); // filtered by released_at
Sum
Totals the values of a column across all matching records:
$this->sum(User::query(), 'revenue');
Average
Calculates the mean value of a column across all matching records:
$this->average(User::query(), 'revenue');
Minimum
Returns the smallest value of a column within the date range:
$this->min(User::query(), 'revenue');
Maximum
Returns the largest value of a column within the date range:
$this->max(User::query(), 'revenue');
Trend
A Trend metric calculates an aggregate grouped over time at a given frequency. Missing dates within the range are automatically filled with zero values.
When the model uses timestamps, the date column defaults to created_at. When the model does not use timestamps, an explicit $dateColumn must be passed or an InvalidArgumentException is thrown.
Extend Trend and implement calculate(), getStartDate(), getEndDate(), and getFrequency():
use AndrewDyer\Metrics\Trend; use AndrewDyer\Metrics\Enums\Frequency; use AndrewDyer\Metrics\Results\TrendResult; use DateTimeImmutable; class UserSignupsOverTime extends Trend { public function calculate(): TrendResult { return $this->count(User::query(), null, 'created_at'); } public function getFrequency(): Frequency { return Frequency::Monthly; } public function getStartDate(): DateTimeImmutable { return new DateTimeImmutable('first day of january this year'); } public function getEndDate(): DateTimeImmutable { return new DateTimeImmutable('last day of december this year'); } }
Calculating the metric returns a keyed array of labels to aggregate values:
$metric = new UserSignupsOverTime(); $result = $metric->calculate(); $result->getResult(); // ['January 2026' => 12, 'February 2026' => 9, ...]
Supported frequencies
Frequency::Daily Frequency::Weekly Frequency::Monthly
Count
Tracks how many records fall within each period of the date range:
$this->count(User::query(), null, 'created_at');
Sum
Totals a column's values for each period across the date range:
$this->sum(User::query(), 'revenue', 'created_at');
Average
Calculates the mean value of a column for each period in the range:
$this->average(User::query(), 'revenue', 'created_at');
Minimum
Returns the lowest value of a column recorded within each period:
$this->min(User::query(), 'revenue', 'created_at');
Maximum
Returns the highest value of a column recorded within each period:
$this->max(User::query(), 'revenue', 'created_at');
Partition
A Partition metric calculates an aggregate grouped by a categorical column, returning a key-value breakdown. Results are filtered to the configured date range.
When the model uses timestamps, the date filter defaults to created_at. When the model does not use timestamps, no date filter is applied unless an explicit $dateColumn is passed.
Extend Partition and implement calculate(), getStartDate(), and getEndDate():
use AndrewDyer\Metrics\Partition; use AndrewDyer\Metrics\Results\PartitionResult; use DateTimeImmutable; class UsersByCountry extends Partition { public function calculate(): PartitionResult { return $this->count(User::query(), 'country'); } public function getStartDate(): DateTimeImmutable { return new DateTimeImmutable('first day of this year'); } public function getEndDate(): DateTimeImmutable { return new DateTimeImmutable('today'); } }
Calculating the metric returns a keyed array of group labels to aggregate values:
$metric = new UsersByCountry(); $result = $metric->calculate(); $result->getResult(); // ['GB' => 42, 'US' => 31, 'DE' => 14]
Count
Groups records by a column and counts how many fall into each category:
$this->count(User::query(), 'country');
To filter by a specific date column, pass it explicitly:
$this->count(User::query(), 'country', null, 'registered_at');
Sum
Groups records by a column and totals a second column within each group:
$this->sum(User::query(), 'country', 'revenue');
Average
Groups records by a column and calculates the mean of a second column per group:
$this->average(User::query(), 'country', 'revenue');
Database Support
The following database drivers are supported:
| Driver | Minimum Version |
|---|---|
| MySQL | 5.7+ |
| MariaDB | 10.2+ |
| SQLite | 3.38.0+ |
| PostgreSQL | 9.4+ |
License
Licensed under the MIT licence and is free for private or commercial projects.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 3
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-02