PHPackages                             moirei/saas-metre - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. moirei/saas-metre

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

moirei/saas-metre
=================

A simple package to manage client usage of your SaaS services.

1.3.0(1mo ago)2509↑1900%MITPHPPHP ^8.2

Since Oct 21Pushed 1mo agoCompare

[ Source](https://github.com/moirei/saas-metre)[ Packagist](https://packagist.org/packages/moirei/saas-metre)[ RSS](/packages/moirei-saas-metre/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (9)Versions (7)Used By (0)

SaaS Metre
==========

[](#saas-metre)

This package is a minimal and straight forward solution for tracking services usage on SaaS applications.

```
$metre = new Metre();

$metre->addMeasure('user_accounts');

$metre->increment('user_accounts');
$metre->increment('user_accounts', count: 2);
$usage = $metre->usage('user_accounts');
expect($usage->count)->toEqual(3);
```

💚 Features
----------

[](#-features)

- Track `METERED` and `VOLUME` measures (service offerings). E.g. tracking user monthly downloads and user allowed storage (for all time).
- Simple period usage accumulator
- Tags to further description usage entries. Can also measure usage per tags.
- Eloquent compatible.

Installation
------------

[](#installation)

```
composer require moirei/saas-metre
```

Concepts
--------

[](#concepts)

**Metre**: A metre is container of measurements for your SaaS offering usage.

**Period**: Usage periods indicating your weekly, monthly, etc., SaaS subscription or billing cycle.

**Measure**: A measure fauture on the metre for your SaaS offering. E.g. `"user_accounts"`, `"auio_downloads"`.

**Measure type**: The types of measuremeants. Currently `METERED` and `VOLUME`. Usage of metreed measurements are calculated per period. E.g. if you provide your users 10 MP3 downloads per week. Volume measurements on the other hand are calculated for all time. E.g. you user may be allowed only a maximum of 2 collaborators at all times.

**Measure limits \[`int`\]**: Used to limit usage of measures.

**Measure tags**: Tags make it possible to categorise and group usage on a single measure.

Usage
-----

[](#usage)

### Create a metre

[](#create-a-metre)

#### With array

[](#with-array)

```
use MOIREI\Metre\Objects\MeasureType;
...

$metre = new Metre([
    'startOfPeriods' => now()->unix(),
    'measures' => [
      'user_accounts' => [
        'type' => MeasureType::METERED,
        'limit' => 100,
        'defaultTags' => ['publisher'],
      ]
    ]
]);
```

#### Make from object value

[](#make-from-object-value)

```
use MOIREI\Metre\Objects\MetreInput;
use MOIREI\Metre\Objects\Measure;
...

$metre = Metre::make(
    new MetreInput(
        startOfPeriods: now()->unix(),
        measures: [
            new Measure(
                name: 'user_accounts',
                type: MeasureType::fromNative('VOLUME'),
                limit: 100,
                defaultTags: ['publisher'],
            ),
        ]
    ),
);
```

#### Build progressively

[](#build-progressively)

```
$metre = new Metre();

// create a measure to limit the amount of "user accounts"
$metre->addMeasure('user_accounts');
$metre->setMeasureType('user_accounts', MeasureType::fromNative('VOLUME')); // set volume since it defaults to "METERED"
$metre->setMeasureLimit('user_accounts', 5);

$metre->addMeasure('orders'
    type: MeasureType::fromNative('METERED'),
    defaultTags: ['sales'],
);
```

### Increment usage

[](#increment-usage)

```
$metre->increment('user_accounts'); // increment usage
$metre->increment('user_accounts', count: 2); // increment usage by 2
```

### Check usability

[](#check-usability)

Use the `canUse` method to determine whether a measure is usable. Returns `bool`.

```
$metre->canUse('user_accounts');
$metre->canUse('user_accounts', count: 2); // If usable by 2 counts
$metre->canUse('user_accounts', tags: [...], period: $period); // Check against tags and period
```

### Get usage

[](#get-usage)

Depending of the measure type (`METERED` or `VOLUME`), calculates usage for current period if metreed. Calculates usage for all time if volumed.

```
$usage = $metre->usage('user_accounts');
$usage->count; // amount used
$usage->limit; // measure/usage limit
$usage->entries; // amount of entries
$usage->percentage(); // get percentage used. Returns null if no limit is set
```

To get usage within a set time, provide a period.

```
$usage = $metre->usage('user_accounts',
    period: now()->subHours(12)->unix(),
);
$usage = $metre->usage('user_accounts',
    period: [
      now()->subDays(2)->unix(), // get usage from this time and ignore measure type
      now()->unix(),
    ],
);
```

### Clear usage

[](#clear-usage)

```
$metre->clear(); // clear all
$metre->clear('user_accounts'); // clear "user_accounts"
$metre->clear('user_accounts', 'orders'); // clear "user_accounts" and "orders"
$metre->clear(['user_accounts', 'orders']); // clear "user_accounts" and "orders"
$metre->clear('unknown_measure'); // fails, "unknown_measure" doesnt exist
```

### Periods

[](#periods)

Start a new period

```
$metre->newPeriod();

// or start a new period for 2 hours from now
$metre->newPeriod(now()->addHours(2));
```

### Tags

[](#tags)

Tags make it possible to categorise and group usage on a single measure. E.g. a *product* purchase, and *ticket* purchase may both be considered orders. However your users' subscription may be billed depending or the type of *sale*.

```
$metre->setMeasureDefaultTags('orders', ['sales']);
$metre->increment('orders', tags: ['product']);
$metre->increment('orders', tags: ['booking']);
$metre->increment('orders', tags: ['ticket', 'booking']);
```

Now usage can be checked per measure tags:

```
expect($metre->usage('orders')->count)->toEqual(3);
expect($metre->usage('orders', tags: ['sales'])->count)->toEqual(3);
expect($metre->usage('orders', tags: ['booking'])->count)->toEqual(2);
expect($metre->usage('orders', tags: ['ticket'])->count)->toEqual(1);
```

### With eloquent attributes

[](#with-eloquent-attributes)

To use directly with Eloquent, use the provided Caster.

```
...
use MOIREI\Metre\MetreCaster;

class Subscription extends Model
{
    ...

    /**
     * The attributes that should be casted.
     *
     * @var array
     */
    protected $casts = [
        ...
        'usage' => MetreCaster::class,
    ];
    ...
}
```

Now, perform user action according to usage status

```
if($user->subscription->usage->canUse('monthly_npm3_downloads')){
  $user->download($file);
  $user->subscription->usage->increment('monthly_npm3_downloads');
}
```

Tests
-----

[](#tests)

```
./vendor/bin/pest
```

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance90

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~322 days

Recently: every ~382 days

Total

6

Last Release

51d ago

PHP version history (2 changes)1.0.0PHP ^8.0

1.3.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/7ac6a15a7b2f9055a98e4419e0d2820f72db3567706837ec388baee535d3e3e7?d=identicon)[moirei](/maintainers/moirei)

---

Top Contributors

[![augustusnaz](https://avatars.githubusercontent.com/u/51074349?v=4)](https://github.com/augustusnaz "augustusnaz (5 commits)")

---

Tags

laravellimitsaasusagemetermoireimetre

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/moirei-saas-metre/health.svg)

```
[![Health](https://phpackages.com/badges/moirei-saas-metre/health.svg)](https://phpackages.com/packages/moirei-saas-metre)
```

###  Alternatives

[spatie/laravel-livewire-wizard

Build wizards using Livewire

4061.0M4](/packages/spatie-laravel-livewire-wizard)[erlandmuchasaj/laravel-gzip

Gzip your responses.

40129.3k2](/packages/erlandmuchasaj-laravel-gzip)[tonysm/importmap-laravel

Use ESM with importmap to manage modern JavaScript in Laravel without transpiling or bundling.

148399.8k1](/packages/tonysm-importmap-laravel)[bensampo/laravel-embed

Painless responsive embeds for videos, slideshows and more.

142146.8k](/packages/bensampo-laravel-embed)[dragon-code/pretty-routes

Pretty Routes for Laravel

10058.7k4](/packages/dragon-code-pretty-routes)[laracraft-tech/laravel-useful-additions

A collection of useful Laravel additions!

58109.4k](/packages/laracraft-tech-laravel-useful-additions)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
