2017 © Pedro Peláez
 

library subscriptions

Subscription handling package for laravel applications

image

ipunkt/subscriptions

Subscription handling package for laravel applications

  • Monday, November 7, 2016
  • by rokde
  • Repository
  • 6 Watchers
  • 11 Stars
  • 52 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 3 Forks
  • 0 Open issues
  • 3 Versions
  • 21 % Grown

The README.md

Subscription handling package for Laravel applications

Latest Stable Version Latest Unstable Version License Total Downloads, (*1)

Installation

Add to your composer.json following lines, (*2)

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

Run php artisan vendor:publish ipunkt/subscriptions, (*3)

Then edit plans.php in config/plans.php to your needs. All known plans are still in there., (*4)

You can use the Subscription facade., (*5)

Run php artisan migrate to migrate the necessary database tables., (*6)

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., (*7)

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

//  @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

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., (*8)

Usage

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., (*9)

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

Getting the current plan for a subscriber

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

Does a subscription already exists for a subscriber

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

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:, (*10)

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

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

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., (*11)

After a subscription was created successfully an event of type Ipunkt\Subscriptions\Subscription\Events\SubscriptionWasCreated gets fired., (*12)

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., (*13)

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

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., (*15)

Getting the current subscription for a subscriber

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

Check subscriber on a Trial

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

Check subscription paid

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

Getting all periods for a subscription

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

Userland code

Fitting in you controllers

We use the laracasts/commander package for handling business commands and events., (*16)

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):, (*17)

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., (*18)

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)
    }
}

The Versions

07/11 2016

dev-master

9999999-dev

Subscription handling package for laravel applications

  Sources   Download

MIT

The Requires

 

by Robert Kummer

laravel php subscriptions plan

07/11 2016

0.1.1

0.1.1.0

Subscription handling package for laravel applications

  Sources   Download

MIT

The Requires

 

by Robert Kummer

laravel php subscriptions plan

04/03 2015

0.1.0

0.1.0.0

Subscription handling package for laravel applications

  Sources   Download

MIT

The Requires

 

by Robert Kummer

laravel php subscriptions plan