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(3mo ago)2509↓87.5%MITPHPPHP ^8.2

Since Oct 21Pushed 3mo 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 3w 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

46

—

FairBetter than 92% of packages

Maintenance82

Actively maintained with recent releases

Popularity15

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

97d 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

[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.1k91.3M280](/packages/laravel-horizon)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[laravel/ai

The official AI SDK for Laravel.

9782.1M162](/packages/laravel-ai)[moonshine/moonshine

Laravel administration panel

1.3k239.9k76](/packages/moonshine-moonshine)[erlandmuchasaj/laravel-gzip

Gzip your responses.

40140.4k2](/packages/erlandmuchasaj-laravel-gzip)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45344.0k1](/packages/pressbooks-pressbooks)

PHPackages © 2026

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