PHPackages                             morenorafael/subscription - 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. [API Development](/categories/api)
4. /
5. morenorafael/subscription

ActiveLibrary[API Development](/categories/api)

morenorafael/subscription
=========================

SaaS style recurring plans for Laravel.

1.0.2(2y ago)1940MITPHP

Since Nov 19Pushed 2y ago1 watchersCompare

[ Source](https://github.com/morenorafael/subscription)[ Packagist](https://packagist.org/packages/morenorafael/subscription)[ RSS](/packages/morenorafael-subscription/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (1)Versions (4)Used By (0)

Subscription
============

[](#subscription)

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

[](#installation)

```
composer require morenorafael/subscription
```

### Service Provider

[](#service-provider)

```
'providers' => [
    /**
    * Third Party Service Providers...
    */
    Morenorafael\Subscription\SubscriptionServiceProvider::class,
...
```

### Config File and Migrations

[](#config-file-and-migrations)

Publish package config file and migrations with the following command:

```
php artisan vendor:publish --provider="Morenorafael\Subscription\SubscriptionServiceProvider"
```

```
php artisan migrate
```

### Traits and Contracts

[](#traits-and-contracts)

Add `Morenorafael\Subscription\Traits\PlanSubscriber` trait and `Morenorafael\Subscription\Contracts\PlanSubscriberInterface` contract to your `User` model.

See the following example:

```
namespace  App\Models;

use Illuminate\Foundation\Auth\User  as  Authenticatable;
use Morenorafael\Subscription\Contracts\PlanSubscriberInterface;
use Morenorafael\Subscription\Traits\PlanSubscriber;

class  User  extends  Authenticatable  implements  PlanSubscriberInterface
{
	use PlanSubscriber;

	...
```

Usage
-----

[](#usage)

### Create a Plan

[](#create-a-plan)

```
use Morenorafael\Subscription\Models\Plan;
use Morenorafael\Subscription\Models\PlanFeature;

$plan = Plan::create([
	'name' => 'Pro',
	'description' => 'Pro plan',
	'price' => 9.99,
	'interval' => 'month',
	'interval_count' => 1,
	'trial_period_days' => 15,
	'sort_order' => 1,
]);

$plan->features()->saveMany([
	new PlanFeature(['code' => 'listings', 'value' => 50, 'sort_order' => 1]),
	new PlanFeature(['code' => 'pictures_per_listing', 'value' => 10, 'sort_order' => 5]),
	new PlanFeature(['code' => 'listing_duration_days', 'value' => 30, 'sort_order' => 10]),
	new PlanFeature(['code' => 'listing_title_bold', 'value' => 'Y', 'sort_order' => 15])
]);

...
```

### Accessing Plan Features

[](#accessing-plan-features)

In some cases you need to access a particular feature in a particular plan, you can accomplish this by using the `getFeatureByCode` method available in the `Plan` model.

Example:

```
$feature = $plan->getFeatureByCode('pictures_per_listing');
$feature->value  // Get the feature's value
```

### Create a Subscription

[](#create-a-subscription)

First, retrieve an instance of your subscriber model, which typically will be your user model and an instance of the plan your user is subscribing to. Once you have retrieved the model instance, you may use the `newSubscription` method (available in `PlanSubscriber` trait) to create the model’s subscription.

```
use Auth;
use Morenorafael\Subscription\Models\Plan;

$user = Auth::user();
$plan = Plan::find(1);

$user->newSubscription('main', $plan)->create();
```

The first argument passed to `newSubscription` method should be the name of the subscription. If your application offer a single subscription, you might call this `main` or `primary`. Subscription’s name is not the Plan’s name, it is an unique subscription identifier. The second argument is the plan instance your user is subscribing to.

### Subscription resolving

[](#subscription-resolving)

When you use the `subscription()` method (i.e., `$user->subscription('main')`) in the subscribable model to retrieve a subscription, you will receive the latest subscription created of the subscribable and the subscription name. For example, if you subscribe Jane Doe to Free plan, and later to Pro plan, Laraplans will return the subscription with the Pro plan because it is the newest subscription available. If you have a different requirement you may use your own subscription resolver by binding an implementation of `Morenorafael\Subscription\Contracts\SubscriptionResolverInterface` to the [service container](https://laravel.com/docs/10.x); like so:

```
/**
 * Register the application services.
 *
 * @return void
 */
public function register()
{
    $this->app->bind(SubscriptionResolverInterface::class, CustomSubscriptionResolver::class);
}
```

### Subscription’s Ability

[](#subscriptions-ability)

There are multiple ways to determine the usage and ability of a particular feature in the user’s subscription, the most common one is `canUse`:

The `canUse` method returns `true` or `false` depending on multiple factors:

- Feature *is enabled*
- Feature value isn’t `0`.
- Or feature has remaining uses available

```
$user->subscription('main')->ability()->canUse('listings');
```

**There are other ways to determine the ability of a subscription:**

- `enabled`: returns `true` when the value of the feature is a *positive word* listed in the config file.
- `consumed`: returns how many times the user has used a particular feature.
- `remainings`: returns available uses for a particular feature.
- `value`: returns the feature value.

All methods share the same signature: `$user->subscription('main')->ability()->consumed('listings');`.

### Record Feature Usage

[](#record-feature-usage)

In order to efectively use the ability methods you will need to keep track of every usage of usage based features. You may use the `record` method available through the user `subscriptionUsage()` method:

The `record` method accepts 3 parameters: the first one is the feature’s code, the second one is the quantity of uses to add (default is `1`), and the third one indicates if the usage should be incremented (`true`: default behavior) or overriden (`false`).

See the following example:

```
// Increment by 2
$user->subscriptionUsage('main')->record('listings', 2);

// Override with 9
$user->subscriptionUsage('main')->record('listings', 9, false);
```

### Reduce Feature Usage

[](#reduce-feature-usage)

Reducing the feature usage is *almost* the same as incrementing it. In this case we only *substract* a given quantity (default is `1`) to the actual usage:

```
// Reduce by 1
$user->subscriptionUsage('main')->reduce('listings');

// Reduce by 2
$user->subscriptionUsage('main')->reduce('listings', 2);
```

### Clear The Subscription Usage Data

[](#clear-the-subscription-usage-data)

In some cases you will need to clear all usages in a particular user subscription, you can accomplish this by using the `clear` method:

```
$user->subscriptionUsage('main')->clear();
```

### Check Subscription Status

[](#check-subscription-status)

For a subscription to be considered **active** the subscription must have an active trial or subscription’s `ends_at` is in the future.

```
$user->subscribed('main');
$user->subscribed('main', $planId); // Check if subscription is active AND using a particular plan
```

Alternatively, you can use the following methods available in the subscription model:

```
$user->subscription('main')->isActive();
$user->subscription('main')->isCanceled();
$user->subscription('main')->isCanceledImmediately();
$user->subscription('main')->isEnded();
$user->subscription('main')->onTrial();
```

> Caution **Canceled** subscriptions **with** an active trial or `ends_at` in the future are considered active.

### Renew a Subscription

[](#renew-a-subscription)

To renew a subscription you may use the `renew` method available in the subscription model. This will set a new `ends_at` date based on the selected plan and **will clear the usage data** of the subscription.

```
$user->subscription('main')->renew();
```

> Caution Canceled subscriptions with an ended period can’t be renewed.

`Morenorafael\Subscription\Events\SubscriptionRenewed` event is fired when a subscription is renewed using the `renew` method.

### Cancel a Subscription

[](#cancel-a-subscription)

To cancel a subscription, simply use the `cancel` method on the user’s subscription:

```
$user->subscription('main')->cancel();
```

By default, the subscription will remain active until the period ends. Pass `true` to *immediately* cancel a subscription.

```
$user->subscription('main')->cancel(true);
```

Events
------

[](#events)

The following are the events fired by the package:

- `Morenorafael\Subscription\Events\SubscriptionCreated`: Fired when a subscription is created.
- `Morenorafael\Subscription\Events\SubscriptionRenewed`: Fired when a subscription is renewed using the `renew()` method.
- `Morenorafael\Subscription\Events\SubscriptionCanceled`: Fired when a subscription is canceled using the `cancel()` method.
- `Morenorafael\Subscription\Events\SubscriptionPlanChanged`: Fired when a subscription’s plan is changed; it will be fired once the `PlanSubscription` model is saved. Plan change is determined by comparing the original and current value of `plan_id`.

Eloquent Scopes
---------------

[](#eloquent-scopes)

```
use Morenorafael\Subscription\Models\PlanSubscription;

// Get subscriptions by plan:
$subscriptions = PlanSubscription::byPlan($plan_id)->get();

// Get subscription by user:
$subscription = PlanSubscription::byUser($user_id)->first();

// Get subscriptions with trial ending in 3 days:
$subscriptions = PlanSubscription::findEndingTrial(3)->get();

// Get subscriptions with ended trial:
$subscriptions = PlanSubscription::findEndedTrial()->get();

// Get subscriptions with period ending in 3 days:
$subscriptions = PlanSubscription::findEndingPeriod(3)->get();

// Get subscriptions with ended period:
$subscriptions = PlanSubscription::findEndedPeriod()->get();

// Exclude subscriptions which are canceled:
$subscriptions = PlanSubscription::excludeCanceled()->get();

// Exclude subscriptions which are immediately canceled:
$subscriptions = PlanSubscription::scopeExcludeImmediatelyCanceled()->get();
```

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity15

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 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 ~67 days

Total

3

Last Release

769d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2c95b60926db40630fd1adcde10b614a4f2946bd8a9a76e0aaafcd7b2bc81279?d=identicon)[morenorafael](/maintainers/morenorafael)

---

Top Contributors

[![morenorafael](https://avatars.githubusercontent.com/u/6283260?v=4)](https://github.com/morenorafael "morenorafael (1 commits)")

---

Tags

laravelsubscriptionsplansmemberships

### Embed Badge

![Health badge](/badges/morenorafael-subscription/health.svg)

```
[![Health](https://phpackages.com/badges/morenorafael-subscription/health.svg)](https://phpackages.com/packages/morenorafael-subscription)
```

###  Alternatives

[mollie/laravel-mollie

Mollie API client wrapper for Laravel &amp; Mollie Connect provider for Laravel Socialite

3624.1M28](/packages/mollie-laravel-mollie)[gerardojbaez/laraplans

SaaS style recurring plans for Laravel.

17817.5k1](/packages/gerardojbaez-laraplans)

PHPackages © 2026

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