Laravel Subscriptions

repository·main·Indexed 42 days ago

https://github.com/laravelcm/laravel-subscriptions

A flexible plans and subscription management system for Laravel applications tailored for SaaS-like services. It provides tools to define plans, manage features with resettable limits, track feature usage, and handle subscription lifecycles including trials, renewals, and cancellations. Note that payment processing is out of scope and must be integrated separately.

Tokens
6.1K
Snippets
19
Records
22
Agent score
54%

What's inside Laravel Subscriptions

  1. Important considerations for Laravel Subscriptions

    main

    Before implementing, keep the following architectural constraints in mind:

    • Payments are out of scope: This package manages plans and subscription logic but does not handle actual payment processing (e.g., Stripe, PayPal). You will need to integrate a payment gateway separately.
    • Extending Core Models: You may need to extend the core models provided by the package if you need to override logic in helper methods such as renew() or cancel(). For example, you might want to trigger a cancellation of a recurring payment in your payment gateway when a subscription is cancelled within the package.
  2. Install Laravel Subscriptions

    main

    To install the package, follow these steps to add the dependency, publish the necessary configuration and migration files, and run the database migrations.

    1. Install via Composer:
      composer require laravelcm/laravel-subscriptions
    2. Publish migrations and config files:
      php artisan vendor:publish --provider="Laravelcm\Subscriptions\SubscriptionServiceProvider"
    3. Run migrations:
      php artisan migrate
    composer require laravelcm/laravel-subscriptions
    php artisan vendor:publish --provider="Laravelcm\Subscriptions\SubscriptionServiceProvider"
    php artisan migrate
  3. Add Subscriptions to a Model

    main

    To enable subscription functionality on any Eloquent model (typically your User model), use the \\Rinvex\\Subscriptions\\Traits\\HasPlanSubscriptions trait. This allows the model to subscribe to plans and manage subscriptions.

    ```php
    namespace App\\\Models;\n\nuse Laravelcm\\Subscriptions\\Traits\\HasPlanSubscriptions;\nuse Illuminate\\Foundation\\Auth\\User as Authenticatable;\n\nclass User extends Authenticatable\n{\n    use HasPlanSubscriptions;\n}\n```
  4. Understand the Feature model

    main

    The Feature model represents a specific capability or limit associated with a subscription Plan. Each feature is tied to a plan via a plan_id and is uniquely identified within that plan by a slug.

    Features can have:

    • Values: A value attribute (string) to define the limit or setting (e.g., '10' for '10 downloads per month').
    • Resettable Limits: Using resettable_period (integer) and resettable_interval (string, e.g., 'month', 'day'), you can define when a feature's usage should reset.
    • Translations: The name and description fields are translatable.
    • Sorting: Features support custom sort orders via the sort_order attribute.
  5. Create a Plan and its Features

    main

    Plans define the billing cycle, price, and trial periods. You can associate multiple features with a plan to control specific usage limits or access rights. Use the Laravelcm\\Subscriptions\\Models\\Plan and Feature models.

    ```php
    use Laravelcm\\Subscriptions\\Models\\Plan;\nuse Laravelcm\\Subscriptions\\Models\\Feature;\nuse Laravelcm\\Subscriptions\\Interval;\n\n$plan = Plan::create([\n    'name' => 'Pro',\n    'description' => 'Pro plan',\n    'price' => 9.99,\n    'signup_fee' => 1.99,\n    'invoice_period' => 1,\n    'invoice_interval' => Interval::MONTH->value,\n    'trial_period' => 15,\n    'trial_interval' => Interval::DAY->value,\n    'sort_order' => 1,\n    'currency' => 'USD',\n]);\n\n// Create multiple plan features at once\n$plan->features()->saveMany([\n    new Feature(['name' => 'listings', 'value' => 50, 'sort_order' => 1]),\n    new Feature(['name' => 'pictures_per_listing', 'value' => 10, 'sort_order' => 5]),\n    new Feature(['name' => 'listing_duration_days', 'value' => 30, 'sort_order' => 10, 'resettable_period' => 1, 'resettable_interval' => 'month']),\n    new Feature(['name' => 'listing_title_bold', 'value' => 'Y', 'sort_order' => 15])\n]);\n```
  6. Get Plan Details

    main

    You can inspect a Plan instance to check its properties and relationships. Features and subscriptions are available as Eloquent collections.

    ```php
    use Laravelcm\\Subscriptions\\Models\\Plan;\n\n$plan = Plan::find(1);\n\n// Get all plan features                \n$plan->features;\n\n// Get all plan subscriptions\n$plan->subscriptions;\n\n// Check if the plan is free\n$plan->isFree();\n\n// Check if the plan has trial period\n$plan->hasTrial();\n\n// Check if the plan has grace period\n$plan->hasGrace();\n```
  7. Manage Subscription Feature Usage

    main

    To track how many times a user uses a feature, use the following methods on the subscription instance (accessed via $user->planSubscription('title')):

    • canUseFeature('name'): Returns true if the feature is enabled, has a non-zero value, or has remaining uses.
    • getFeatureUsage('name'): Returns current usage count.
    • getFeatureRemainings('name'): Returns remaining uses.
    • getFeatureValue('name'): Returns the feature's configured value.
    • recordFeatureUsage('name', [quantity], [is_incremental]): Increments usage. Set third param to false to override usage with the provided quantity.
    • reduceFeatureUsage('name', [quantity]): Decrements usage.
    • usage()->delete(): Clears all usage data for the subscription.
    ```php
    // Check if user can use a feature
    $user->planSubscription('main')->canUseFeature('listings');\n\n// Record usage (increment by 2)
    $user->planSubscription('main')->recordFeatureUsage('listings', 2);\n\n// Record usage (override with 9)
    $user->planSubscription('main')->recordFeatureUsage('listings', 9, false);\n\n// Reduce usage\n$user->planSubscription('main')->reduceFeatureUsage('listings', 2);\n\n// Clear usage data\n$user->planSubscription('main')->usage()->delete();\n```
  8. Retrieve Feature Values

    main

    There are three ways to retrieve a feature's value depending on the context:

    1. From a Plan instance: $plan->getFeatureBySlug('slug')->value
    2. Directly via the Feature model: Feature::where('slug', 'slug')->first()->value
    3. Through a Subscription instance: $subscription->getFeatureValue('slug')
    ```php
    use Laravelcm\\Subscriptions\\Models\\Feature;\nuse Laravelcm\\Subscriptions\\Models\\Subscription;\n\n// Use the plan instance to get feature's value\n$amountOfPictures = $plan->getFeatureBySlug('pictures_per_listing')->value;\n\n// Query the feature itself directly\n$amountOfPictures = Feature::where('slug', 'pictures_per_listing')->first()->value;\n\n// Get feature value through the subscription instance\n$amountOfPictures = Subscription::find(1)->getFeatureValue('pictures_per_listing');\n```
  9. Change a Subscription Plan

    main

    Use the changePlan method on a Subscription instance to switch plans.

    Important Behavior:

    • If the billing frequency (invoice_period and invoice_interval) remains the same, billing dates are retained.
    • If the billing frequency changes, the new frequency starts immediately and subscription usage data is cleared.
    ```php
    use Laravelcm\\Subscriptions\\Models\\Plan;\nuse Laravelcm\\Subscriptions\\Models\\Subscription;\n\n$plan = Plan::find(2);\n$subscription = Subscription::find(1);\n\n// Change subscription plan\n$subscription->changePlan($plan);\n```
  10. Renew or Cancel a Subscription

    main

    Manage the lifecycle of a subscription:

    • Renew: Use renew() on the subscription instance. This sets a new ends_at date and clears usage data. Note: Canceled subscriptions with an ended period cannot be renewed.
    • Cancel: Use cancel() on the subscription instance. By default, it remains active until the end of the period. Pass true to cancel(true) to end the subscription immediately.
    ```php
    // Renew subscription
    $user->planSubscription('main')->renew();\n\n// Cancel subscription (end at period end)\n$user->planSubscription('main')->cancel();\n\n// Cancel subscription (end immediately)\n$user->planSubscription('main')->cancel(true);\n```
  11. Create a Subscription

    main

    Use the newPlanSubscription method (provided by the HasPlanSubscriptions trait) to subscribe a model to a plan. The first argument is a unique title for the subscription (e.g., 'main'). The second is the Plan instance. An optional third argument allows setting a custom start date using a Carbon\\Carbon instance.

    ```php
    use Laravelcm\\Subscriptions\\Models\\Plan;\nuse App\\Models\\User;\n\n$user = User::find(1);\n$plan = Plan::find(1);\n\n$user->newPlanSubscription('main', $plan);\n```
  12. Check Subscription Status

    main

    A subscription is considered active if it has an active trial OR if ends_at is in the future.

    Use $user->subscribedTo($planId) for a quick check, or use specific methods on the subscription instance:

    • active()
    • canceled()
    • ended()
    • onTrial()
    ```php
    // Check if user is subscribed to a specific plan ID
    $user->subscribedTo($planId);\n\n// Detailed status checks on the subscription instance
    $user->planSubscription('main')->active();\n$user->planSubscription('main')->canceled();\n$user->planSubscription('main')->ended();\n$user->planSubscription('main')->onTrial();\n```