omnitaskba / laravel-model-metrics
Easily attach time-based metrics to any Eloquent model.
Installs: 4
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/omnitaskba/laravel-model-metrics
Requires
- php: ^8.2
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1|^7.10.0
- nunomaduro/larastan: ^3.8
- orchestra/testbench: ^9.0
- pestphp/pest: ^2.34
- pestphp/pest-plugin-laravel: ^2.3
- phpstan/phpstan: ^2.1
- phpstan/phpstan-strict-rules: ^2.0
- roave/security-advisories: dev-latest
This package is auto-updated.
Last update: 2025-12-11 11:21:15 UTC
README
Laravel Model Metrics ๐
A simple and non-intrusive Laravel package that enables daily time-series metrics and aggregated single-value metrics for any Eloquent model --- without adding clutter to your main tables.
Perfect for tracking views, logins, sales, XP, streaks, and more.
๐ Features
- ๐
Daily Metrics: Store values tracked per day (
year,month,day). - ๐งฎ Aggregated Metrics: Store a single key-value score (e.g., current streak).
- ๐ท๏ธ Supports Strings or PHP Backed Enums for metric names.
- โก Efficient: Uses dedicated tables and optimized SUM queries.
- ๐ Plug-and-Play: Activated by a single trait.
- ๐ ๏ธ Configurable: Customize table names easily.
๐ฆ Installation
1. Install via Composer
composer require omnitaskba/laravel-model-metrics
2. Run Migrations
The package creates two dedicated tables: model_metrics and model_aggregated_metrics.
php artisan migrate
3. Add the trait to your model
Apply the HasMetrics trait to any Eloquent model you wish to track metrics for.
// app/Models/User.php use Omnitaskba\ModelMetrics\Traits\HasMetrics; use Illuminate\Database\Eloquent\Model; class User extends Model { use HasMetrics; // ... }
๐ Usage
Metric names can be passed as a string ('views') or, preferably, as a Backed Enum (PHP 8.1+):
// Example Backed Enum enum UserMetric: string { case VIEWS = 'views'; case SALES = 'sales'; case STREAK = 'streak'; case HIGH_SCORE = 'high_score'; // ... }
Daily & Aggregated Metrics Documentation
๐ Daily Metrics (Time Series)
Daily metrics are stored by day (year, month, day) and track historical, timeโsensitive data.
1. incrementDailyMetric()
Increments the metric value for the current day. Creates the daily record if it doesn't exist.
| Argument | Type | Default | Description |
|---|---|---|---|
name |
string or BackedEnum | Required | The name of the metric (e.g., UserMetric::HIGH_SCORE). |
value |
float | 1.0 | Amount to increment by. |
Example
// Assuming current date is 2025-12-09 $user->incrementDailyMetric(UserMetric::HIGH_SCORE); // Value: 1.0 $user->incrementDailyMetric(UserMetric::HIGH_SCORE, 5.5); // Value: 6.5
Returns: New value of the metric record.
2. decrementDailyMetric()
Decrements the metric value for the current day. Creates the daily record if it doesn't exist.
| Argument | Type | Default | Description |
|---|---|---|---|
name |
string or BackedEnum | Required | The metric name. |
value |
float | 1.0 | Amount to decrement by. |
Example
// Assuming current daily high_score are 20.0 $user->decrementDailyMetric(UserMetric::HIGH_SCORE, 0.5);
Returns: New value (19.5 in this case).
3. getTodayMetric()
Retrieves today's metric value.
| Argument | Type | Default | Description |
|---|---|---|---|
name |
string or BackedEnum | Required | Metric name. |
Example
$todayViews = $user->getTodayMetric(UserMetric::HIGH_SCORE);
Returns:
float(19.5) --- or 0.0 if none exists.
4. getTotalMetric()
Calculates the sum across all days between two dates (inclusive).
| Argument | Type | Default | Description |
|---|---|---|---|
name |
string or BackedEnum | Required | Metric name. |
startDate |
DateTimeInterface | null | Start date. |
endDate |
DateTimeInterface | null | End date. |
Example
use DateTime; $start = new DateTime('2025-10-01'); $end = new DateTime('2025-10-31'); $totalSales = $user->getTotalMetric(ProductMetric::SALES, $start, $end);
Returns: float(1250.0) or 0.0 if no data.
5. getTotalForPastDays()
Sums the metric for the last N days (including today).
| Argument | Type | Default | Description |
|---|---|---|---|
name |
string or BackedEnum | Required | Metric name. |
days |
int | Required | How many days to look back. |
Example
$lastWeekViews = $user->getTotalForPastDays(ProductMetric::VIEWS, 7);
Returns: float(85.5)
6. getMetricHistory()
Retrieves a collection of daily metric records grouped by day, sorted descending.
| Argument | Type | Default | Description |
|---|---|---|---|
name |
string or BackedEnum | Required | Metric name. |
limit |
int | 30 | Max number of records. |
Example
$history = $user->getMetricHistory(ProductMetric::VIEWS, 10);
๐ Aggregated Metrics (Single Value)
Aggregated metrics store a single persistent value.
1. setAggregatedMetric()
Sets or overwrites the metric value.
| Argument | Type | Default | Description |
|---|---|---|---|
name |
string or BackedEnum | Required | Metric name. |
value |
float | Required | Value to set. |
Example
$user->setAggregatedMetric(UserMetric::HIGH_SCORE, 999.5);
2. incrementAggregatedMetric()
Increases the metric value.
| Argument | Type | Default | Description |
|---|---|---|---|
name |
string or BackedEnum | Required | Metric name. |
value |
float | 1.0 | Increment amount. |
Example
$user->incrementAggregatedMetric(UserMetric::LOGIN_STREAK); // New value: 6.0
3. decrementAggregatedMetric()
Decreases the value.
| Argument | Type | Default | Description |
|---|---|---|---|
name |
string or BackedEnum | Required | Metric name. |
value |
float | 1.0 | Decrement amount. |
Example
$user->decrementAggregatedMetric(UserMetric::HIGH_SCORE, 5.5); // New value: 94.5
4. getAggregatedMetric()
Retrieves current aggregated value.
Example
$currentScore = $user->getAggregatedMetric(UserMetric::HIGH_SCORE);
Returns: float(999.5) (or 0.0 if missing)
5. hasAggregatedMetric()
Checks if the record exists.
Example
if ($user->hasAggregatedMetric(UserMetric::HIGH_SCORE)) { // ... }
6. resetAggregatedMetric()
Sets value to 0.0 (record stays).
Example
$user->resetAggregatedMetric(UserMetric::LOGIN_STREAK);
7. clearAggregatedMetric()
Deletes the aggregated metric record entirely.
Example
$user->clearAggregatedMetric('old_metric');
Returns: true on success, false if not found.
โ๏ธ Configuration
You can publish the configuration file to customize the table names used by the package:
php artisan vendor:publish --tag=model-metrics-config
This will create a config/model-metrics.php file with the following contents, allowing you to customize the table names and model classes used for each metric type:
// config/model-metrics.php return [ 'time_series' => [ 'table_name' => 'model_metrics', 'model' => \Omnitaskba\ModelMetrics\Models\Metric::class, ], 'aggregated' => [ 'table_name' => 'model_aggregated_metrics', 'model' => \Omnitaskba\ModelMetrics\Models\AggregatedMetric::class, ], ];
Key Configuration Options:
time_series.table_name: The table used for Daily Metrics (Time Series).aggregated.table_name: The table used for Aggregated Metrics (Single Value).
๐ง Performance Notes
- Indexes: The underlying tables (metrics and aggregated_metrics) are indexed on the required columns (name, model_id, model_type, and date columns) to ensure rapid retrieval and SUM operations.
- Unique Constraints: Daily metrics use a unique constraint on (name, year, month, day, model_id, model_type) to prevent duplicate entries and ensure atomic updates.
๐งช Testing
You can run the full test suite with:
composer test
๐ค Contributing
See CONTRIBUTING.md.
๐ Changelog
Please see CHANGELOG.md for more information what has changed recently.
๐ Security
If you discover any security related issues, please email zlatan@omnitask.ba instead of using the issue tracker.
๐ก Credits
๐ License
Laravel Model Metrics is open-sourced software licensed under the MIT License.
