PHPackages                             ipunkt/subscriptions - 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. ipunkt/subscriptions

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

ipunkt/subscriptions
====================

Subscription handling package for laravel applications

1.0.2(5y ago)132314MITPHPPHP &gt;=7.4.0

Since Mar 4Pushed 5y ago6 watchersCompare

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

READMEChangelog (5)Dependencies (5)Versions (6)Used By (0)

Subscription handling package for Laravel applications
======================================================

[](#subscription-handling-package-for-laravel-applications)

[![Latest Stable Version](https://camo.githubusercontent.com/e87758468971bd640065a43786bbe470b0bf92cf528efec05aa4533bc3be90e8/68747470733a2f2f706f7365722e707567782e6f72672f6970756e6b742f737562736372697074696f6e732f762f737461626c652e737667)](https://packagist.org/packages/ipunkt/subscriptions) [![Latest Unstable Version](https://camo.githubusercontent.com/745469d6a6ec9b995ffcd6047238b5390020e9c87f76e29830fd59cfeff5e954/68747470733a2f2f706f7365722e707567782e6f72672f6970756e6b742f737562736372697074696f6e732f762f756e737461626c652e737667)](https://packagist.org/packages/ipunkt/subscriptions) [![License](https://camo.githubusercontent.com/9c7022873a11f02e749f21ddd01eb42b35b2164a016ac92833438d9bba1533e2/68747470733a2f2f706f7365722e707567782e6f72672f6970756e6b742f737562736372697074696f6e732f6c6963656e73652e737667)](https://packagist.org/packages/ipunkt/subscriptions) [![Total Downloads](https://camo.githubusercontent.com/4f805338da449a77c617ffe961189d123e2de9435c87a6a68833092a1567f755/68747470733a2f2f706f7365722e707567782e6f72672f6970756e6b742f737562736372697074696f6e732f646f776e6c6f6164732e737667)](https://packagist.org/packages/ipunkt/subscriptions)

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

[](#installation)

Add to your composer.json following lines

```
"require": {
	"ipunkt/subscriptions": "^1.0"
}

```

Run `php artisan vendor:publish ipunkt/subscriptions`

Then edit `plans.php` in `config/plans.php` to your needs. All known plans are still in there.

You can use the `Subscription` facade.

Run `php artisan migrate` to migrate the necessary database tables.

Configuration
-------------

[](#configuration)

### Plan configuration

[](#plan-configuration)

```
//  @see src/config/plans.php
return [
	'PLAN-ID' => [
		'name' => 'TRIAL',
		'description' => 'Trial subscription.',
		'subscription_break' => 0,  // optional for preventing a subscription for X days after last subscription ends
	],
];

```

The optional property `'subscription_break` can be used to prevent a subscriber to subscribe to this plan before a configured count of days will be gone. This is for example to have a TRIAL plan which can be subscribed to only once a year.

#### Benefit configuration for a plan

[](#benefit-configuration-for-a-plan)

```
//  @see src/config/plans.php
return [
	'PLAN-ID' => [
		// [..]
		'benefits' => [
			'feature-1' => [],  // feature is present
			'feature-2-countable' => [
				'min' => 10,    // feature is present and has margins/countable range
			],
			'feature-3-countable' => [
				'min' => 10,
				'max' => 50,
			],
			'feature-4-countable' => [
				'max' => 50,    // min is automatically 0 (zero)
			],
		],
	],
];

```

#### Payment options for a plan

[](#payment-options-for-a-plan)

```
//  @see src/config/plans.php
return [
    'PLAN-ID' => [
        // [..]
        'payments' => [
            [
                'price' => 1,           // for 1.00
                'quantity' => 12,       // in 12-times
                'days' => 30,           // of 30-days
                'methods' => ['paypal'], // allowed payment methods
            ],
            [
                'price' => 2,           // for 2.00
                'quantity' => 12,       // in 12-times
                'days' => 30,           // of 30-days
                'methods' => ['paypal', 'invoice'],
            ],
        ],
    ],
];

```

#### Choosing a default plan for all subscribers

[](#choosing-a-default-plan-for-all-subscribers)

For setting a default plan to all subscribers you can use the `src/config/defaults.php` and set the id for the default plan. So every call on plan-based feature checking will resolve this default plan when the subscriber has no plan yet.

Usage
-----

[](#usage)

### Getting all plans

[](#getting-all-plans)

```
/** @var Plan[] $plans */
$plans = Subscription::plans();

```

If you use the subscription break in your plan configuration, fetch all plans with the `selectablePlans` method. This checks the last subscription for each breaking plan.

```
/** @var Plan[] $plans */
$plans = Subscription::selectablePlans($this->user);

```

### Getting the current plan for a subscriber

[](#getting-the-current-plan-for-a-subscriber)

```
/** @var Plan|null $plan */
$plan = Subscription::plan($subscriber);

```

### Does a subscription already exists for a subscriber

[](#does-a-subscription-already-exists-for-a-subscriber)

```
Subscription::exists($subscriber); // returns true when a subscription exists

```

### Each plan can have benefits (features)

[](#each-plan-can-have-benefits-features)

```
$plan->can('feature');               // returns true or false
$plan->can('countable-feature', 14); // returns true or false

```

Or use the `Subscription` facade instead to check against current subscription plan for a subscriber. This is recommended:

```
Subscription::can($subscriber, 'feature');               // returns true or false
Subscription::can($subscriber, 'countable-feature', 14); // returns true or false

```

### Getting all possible payment options for a plan

[](#getting-all-possible-payment-options-for-a-plan)

```
/** @var PaymentOption[] $paymentOptions */
$paymentOptions = $plan->paymentOptions();

```

### Creating a new subscription

[](#creating-a-new-subscription)

```
/** creating a subscription for a subscriber, maybe the current authenticated user */
$subscription = Subscription::create($plan, $paymentOption, SubscriptionSubscriber $subscriber);

```

For creating a subscription you have to give the `Plan` or the id of a plan and the selected `PaymentOption`or the identifier for the payment option. The `$subscriber` is the entity the subscription belongs to. This can be any morphable eloquent object.

After a subscription was created successfully an event of type `Ipunkt\Subscriptions\Subscription\Events\SubscriptionWasCreated` gets fired.

The underlying repository controls for duplicates itself. So for existing subscriptions it will update the current subscription and fires an event of type `Ipunkt\Subscriptions\Subscription\Events\SubscriptionWasUpdated`instead.

You can upgrade the subscription to any other plan. The same method `Subscription::create()` handles this upgrade.

The fired events have both the current subscription, the selected plan and the payment option as properties. So you can listen on these events and do your own stuff.

### Getting the current subscription for a subscriber

[](#getting-the-current-subscription-for-a-subscriber)

```
/** @var Subscription|null $subscription */
$subscription = Subscription::current($subscriber);

```

### Check subscriber on a Trial

[](#check-subscriber-on-a-trial)

```
/** be careful because current() can return null when no subscription existing */
$onTrial = Subscription::current($subscriber)->onTrial();

```

### Check subscription paid

[](#check-subscription-paid)

```
$subscription = Subscription::current($subscriber);
$isPaid = $subscription->paid(); // or Subscription::paid($subscriber);

```

### Getting all periods for a subscription

[](#getting-all-periods-for-a-subscription)

```
/** @var Period[] $periods */
$periods = $subscription->periods;

```

Userland code
-------------

[](#userland-code)

### Fitting in you controllers

[](#fitting-in-you-controllers)

We use the `laracasts/commander` package for handling business commands and events.

```
class SubscriptionsController extends \Controller
{
	/**
     * use commandbus to execute commands
     */
    use Laracasts\Commander\CommanderTrait;

    // display an overview of all subscriptions
    public function index()
    {
        $subscribed = Subscription::exists($this->user);// $this->user represents a SubscriptionSubscriber interface
        if ( ! $subscribed) {
            $plans = Subscription::selectablePlans($this->user);    // unselectable plans filtered out already
            $defaultPlan = Subscription::plan($this->user);

            return View::make('subscriptions.create', compact('plans', 'defaultPlan'));
        }

        $plan = Subscription::plan($this->user);
        $subscription = Subscription::current($this->user);

        $paid = $subscription->paid();

        $subscriptions = Subscription::all($this->user);

        return View::make('subscriptions.index', compact('subscribed', 'plan', 'subscription', 'subscriptions', 'paid'));
    }

    //  create a plan (form)
    public function create($plan)
    {
        $plan = Subscription::findPlan($plan);

        $subscription = Subscription::all($this->user)->last();
        if (null !== $subscription && $subscription->subscription_ends_at->isPast())
            $subscription = null;

        $startDate = (null === $subscription) ? Carbon::now() : $subscription->subscription_ends_at->addSeconds(1);

        return View::make('subscriptions.create_plan', compact('plan', 'startDate'));
    }

    //  store the plan as subscription for user
    public function store()
    {
        try {
            $this->validate(Input::all());
        } catch (FormValidationException $e)
        {
            return Redirect::back()->withInput()->withErrors($e->getErrors());
        }

        $plan = Subscription::findPlan(Input::get('plan'));
        if (null === $plan)
            throw (new ModelNotFoundException('No plan ' . Input::get('plan') . ' found.'))->setModel(Plan::class);

        $this->execute(CreateSubscriptionCommand::class, Input::all());

        Flash::success('subscriptions.subscription_created');

        return Redirect::route('subscriptions.index');
    }
}

```

And the corresponding command `CreateSubscriptionCommandHandler` is here (The `CreateSubscriptionCommand` is only a DTO for the input values):

```
class CreateSubscriptionCommandHandler implements Laracasts\Commander\CommandHandler
{
	use Laracasts\Commander\Events\DispatchableTrait;

	/**
     * authenticated user
     *
     * @var \Illuminate\Auth\Guard
     */
    private $auth;

    /**
     * @param AuthManager $auth
     */
    public function __construct(\Illuminate\Auth\AuthManager $auth)
    {
        $this->auth = $auth;
    }

	/**
     * Handle the command
     *
     * @param CreateSubscriptionCommand $command
     * @return mixed
     */
    public function handle($command)
    {
        /** @var User|SubscriptionSubscriber $user */
        $user = $this->auth->user();

        //  store invoice data

        //  create subscription
        $subscription = Subscription::create($command->plan, $command->payment_option, $user);

        //  fire event for "subscription created" or "subscription updated"
        $this->dispatchEventsFor($subscription);
    }
}

```

Nearly the same you have to do for extending or upgrading a plan. You can use the same command, handler and controller action. The subscription repository handles automatically an update or create for a subscription plan.

### Registering a Listener

[](#registering-a-listener)

```
# in your app/listeners.php for example
Event::listen('Ipunkt.Subscriptions.Subscription.Events.*', 'App\Subscriptions\Listeners\EmailNotifier');

//  we use the laracasts/commander package, so you can inform you about a listener too
class EmailNotifier extends Laracasts\Commander\Events\EventListener
{
    /**
     * will be called when event SubscriptionWasCreated was fired
     *
     * @param SubscriptionWasCreated $event
     */
    public function whenSubscriptionWasCreated(SubscriptionWasCreated $event)
    {
        //  do something when a subscription was created (a new plan was set up and no plan exists before
        //  or every plan subscription before was in the past)
    }

    /**
     * will be called when event SubscriptionWasUpdated was fired
     *
     * @param SubscriptionWasUpdated $event
     */
    public function whenSubscriptionWasUpdated(SubscriptionWasUpdated $event)
    {
        //  do something when a subscription was updated (e.g. smaller plan before gets upgraded to a more-featured
        //  plan or a subscription was extended to get longer running)
    }
}

```

###  Health Score

32

—

LowBetter than 71% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity67

Established project with proven stability

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

Total

5

Last Release

2127d ago

Major Versions

0.1.1 → 1.0.02020-06-26

PHP version history (2 changes)0.1.0PHP &gt;=5.4.0

1.0.0PHP &gt;=7.4.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/4946056?v=4)[Robert Kummer](/maintainers/rokde)[@rokde](https://github.com/rokde)

---

Tags

phplaravelsubscriptionsplan

### Embed Badge

![Health badge](/badges/ipunkt-subscriptions/health.svg)

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

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3274.9M308](/packages/psalm-plugin-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k12.1M99](/packages/laravel-pulse)[laragear/preload

Effortlessly make a Preload script for your Laravel application.

119363.5k](/packages/laragear-preload)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[spatie/laravel-enum

Laravel Enum support

3655.4M31](/packages/spatie-laravel-enum)[napp/xray-laravel

AWS X-Ray for Laravel applications.

61407.3k](/packages/napp-xray-laravel)

PHPackages © 2026

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